def test_undefined_filter_criteria(self): with pytest.raises(InternalServerError): CohortFilter.create( uid=asc_advisor_uid, label='Cohort with undefined filter criteria', genders=[], in_intensive_cohort=None, )
def test_undefined_filter_criteria(self): with pytest.raises(InternalServerError): CohortFilter.create( uid=asc_advisor_uid, name='Cohort with undefined filter criteria', filter_criteria={ 'genders': [], 'inIntensiveCohort': None, }, )
def create_cohort(): params = request.get_json() domain = get_param(params, 'domain', 'default') if is_unauthorized_domain(domain): raise ForbiddenRequestError( f'You are unauthorized to query the \'{domain}\' domain') name = get_param(params, 'name', None) filters = get_param(params, 'filters', None) order_by = params.get('orderBy') # Authorization check filter_keys = list(map(lambda f: f['key'], filters)) if is_unauthorized_search(filter_keys, order_by): raise ForbiddenRequestError( 'You are unauthorized to access student data managed by other departments' ) filter_criteria = _translate_filters_to_cohort_criteria(filters, domain) if not name or not filter_criteria: raise BadRequestError( 'Cohort creation requires \'name\' and \'filters\'') cohort = CohortFilter.create( uid=current_user.get_uid(), name=name, filter_criteria=filter_criteria, domain=domain, order_by=order_by, include_alerts_for_user_id=current_user.get_id(), ) _decorate_cohort(cohort) return tolerant_jsonify(cohort)
def test_create_and_delete_cohort(self): """Cohort_filter record to Flask-Login for recognized UID.""" owner = AuthorizedUser.find_by_uid(asc_advisor_uid).uid shared_with = AuthorizedUser.find_by_uid(coe_advisor_uid).uid # Check validity of UIDs assert owner assert shared_with # Create and share cohort group_codes = ['MFB-DB', 'MFB-DL', 'MFB-MLB', 'MFB-OLB'] cohort = CohortFilter.create( uid=owner, name='Football, Defense', filter_criteria={ 'groupCodes': group_codes, }, ) cohort_id = cohort['id'] CohortFilter.share(cohort_id, shared_with) owners = CohortFilter.find_by_id(cohort_id)['owners'] assert len(owners) == 2 assert owner, shared_with in [user['uid'] for user in owners] assert cohort['totalStudentCount'] == len( CohortFilter.get_sids(cohort_id)) # Delete cohort and verify previous_owner_count = cohort_count(owner) previous_shared_count = cohort_count(shared_with) CohortFilter.delete(cohort_id) assert cohort_count(owner) == previous_owner_count - 1 assert cohort_count(shared_with) == previous_shared_count - 1
def test_filter_criteria(self): gpa_ranges = [ 'numrange(0, 2, \'[)\')', 'numrange(2, 2.5, \'[)\')', ] group_codes = ['MFB-DB', 'MFB-DL'] levels = ['Junior'] majors = ['Environmental Economics & Policy', 'Gender and Women\'s Studies'] unit_ranges = [ 'numrange(0, 5, \'[]\')', 'numrange(30, NULL, \'[)\')', ] cohort = CohortFilter.create( uid='1022796', label='All criteria, all the time', gpa_ranges=gpa_ranges, group_codes=group_codes, in_intensive_cohort=None, levels=levels, majors=majors, unit_ranges=unit_ranges, ) cohort = CohortFilter.find_by_id(cohort.id) expected = { 'gpaRanges': gpa_ranges, 'groupCodes': group_codes, 'inIntensiveCohort': None, 'levels': levels, 'majors': majors, 'unitRanges': unit_ranges, } def sort_and_format(filter_criteria): return json.dumps(filter_criteria, sort_keys=True, indent=2) assert sort_and_format(expected) == sort_and_format(cohort.filter_criteria)
def test_cohort_update_filter_criteria(self, client, asc_advisor_session): label = 'Swimming, Men\'s' original_student_count = 4 cohort = CohortFilter.create( uid=asc_advisor_uid, label=label, group_codes=['MSW', 'MSW-DV', 'MSW-SW'], student_count=original_student_count, ) assert original_student_count > 0 updated_filter_criteria = { 'groupCodes': ['MSW-DV', 'MSW-SW'], } data = { 'id': cohort.id, 'filterCriteria': updated_filter_criteria, 'studentCount': original_student_count - 1, } response = client.post('/api/filtered_cohort/update', data=json.dumps(data), content_type='application/json') assert 200 == response.status_code updated_cohort = CohortFilter.find_by_id(int(response.json['id'])) assert updated_cohort.label == label assert updated_cohort.student_count == original_student_count - 1 def remove_empties(filter_criteria): return {k: v for k, v in filter_criteria.items() if v is not None} expected = remove_empties(cohort.filter_criteria) actual = remove_empties(updated_cohort.filter_criteria) assert expected == actual
def create_cohort(): params = request.get_json() if is_unauthorized_search(params): raise ForbiddenRequestError( 'You are unauthorized to access student data managed by other departments' ) label = util.get(params, 'label', None) if not label: raise BadRequestError('Cohort creation requires \'label\'') cohort = CohortFilter.create( advisor_ldap_uids=util.get(params, 'advisorLdapUids'), coe_prep_statuses=util.get(params, 'coePrepStatuses'), ethnicities=util.get(params, 'ethnicities'), genders=util.get(params, 'genders'), gpa_ranges=util.get(params, 'gpaRanges'), group_codes=util.get(params, 'groupCodes'), in_intensive_cohort=util.to_bool_or_none( params.get('inIntensiveCohort')), is_inactive_asc=util.to_bool_or_none(params.get('isInactiveAsc')), label=label, last_name_range=util.get(params, 'lastNameRange'), levels=util.get(params, 'levels'), majors=util.get(params, 'majors'), uid=current_user.get_id(), underrepresented=util.get(params, 'underrepresented'), unit_ranges=util.get(params, 'unitRanges'), ) return tolerant_jsonify(decorate_cohort(cohort))
def test_cohort_update(self): cohort = CohortFilter.create(label='Football teams', team_codes=['FBM', 'FBW'], uid='2040') foosball_label = 'Foosball teams' cohort = CohortFilter.update(cohort['id'], foosball_label) assert cohort['label'] == foosball_label
def test_create_and_delete_cohort(self): """Cohort_filter record to Flask-Login for recognized UID.""" owner = AuthorizedUser.find_by_uid(asc_advisor_uid).uid # Check validity of UID assert owner # Create cohort group_codes = ['MFB-DB', 'MFB-DL', 'MFB-MLB', 'MFB-OLB'] cohort = CohortFilter.create( uid=owner, name='Football, Defense', filter_criteria={ 'groupCodes': group_codes, }, ) cohort_id = cohort['id'] assert CohortFilter.find_by_id(cohort_id)['owner']['uid'] == owner assert cohort['totalStudentCount'] == len( CohortFilter.get_sids(cohort_id)) # Delete cohort and verify previous_owner_count = cohort_count(owner) CohortFilter.delete(cohort_id) std_commit(allow_test_environment=True) assert cohort_count(owner) == previous_owner_count - 1
def test_unauthorized_cohort_update(self, client, coe_advisor_session): cohort = CohortFilter.create(uid=asc_advisor_uid, label='Swimming, Men\'s', group_codes=['MSW', 'MSW-DV', 'MSW-SW']) data = { 'id': cohort.id, 'label': 'Hack the label!', } response = client.post('/api/filtered_cohort/update', data=json.dumps(data), content_type='application/json') assert 403 == response.status_code
def test_delete_cohort(self, client, coe_advisor_session): """Deletes existing custom cohort while enforcing rules of ownership.""" label = 'Water polo teams' cohort = CohortFilter.create(uid=coe_advisor_uid, label=label, group_codes=['WWP', 'MWP']) # Verify deletion response = client.delete(f'/api/filtered_cohort/delete/{cohort.id}') assert response.status_code == 200 cohorts = CohortFilter.all_owned_by(coe_advisor_uid) assert not next((c for c in cohorts if c.id == cohort.id), None)
def test_delete_cohort_wrong_user(self, client, fake_auth): """custom cohort deletion is only available to owners""" cohort = CohortFilter.create(label='Badminton teams', team_codes=['MBK', 'WBK'], uid=test_uid) assert cohort and 'id' in cohort # This user does not own the custom cohort above fake_auth.login('2040') response = client.delete('/api/cohort/delete/{}'.format(cohort['id'])) assert response.status_code == 400 assert '2040 does not own' in str(response.data)
def create_cohort(): params = request.get_json() label = params['label'] team_codes = params['team_codes'] if not label or not team_codes: raise BadRequestError( 'Cohort creation requires \'label\' and \'teams\'') cohort = CohortFilter.create(label=label, team_codes=team_codes, uid=current_user.get_id()) return tolerant_jsonify(cohort)
def test_filter_criteria(self): gpa_ranges = [ { 'min': 0, 'max': 1.999 }, { 'min': 2, 'max': 2.499 }, ] group_codes = ['MFB-DB', 'MFB-DL'] intended_majors = ['Public Health BA'] levels = ['Junior'] majors = [ 'Environmental Economics & Policy', 'Gender and Women\'s Studies' ] minors = ['Physics UG'] unit_ranges = [ 'numrange(0, 5, \'[]\')', 'numrange(30, NULL, \'[)\')', ] cohort = CohortFilter.create( uid='1022796', name='All criteria, all the time', filter_criteria={ 'gpaRanges': gpa_ranges, 'groupCodes': group_codes, 'inIntensiveCohort': None, 'intendedMajors': intended_majors, 'levels': levels, 'majors': majors, 'minors': minors, 'unitRanges': unit_ranges, }, ) cohort_id = cohort['id'] cohort = CohortFilter.find_by_id(cohort_id) expected = { 'gpaRanges': gpa_ranges, 'groupCodes': group_codes, 'inIntensiveCohort': None, 'intendedMajors': intended_majors, 'levels': levels, 'majors': majors, 'minors': minors, 'unitRanges': unit_ranges, } for key, value in expected.items(): assert cohort['criteria'][key] == expected[key] assert cohort['totalStudentCount'] == len( CohortFilter.get_sids(cohort_id))
def test_delete_cohort(self, authenticated_session, client): """deletes existing custom cohort while enforcing rules of ownership""" label = 'Water polo teams' cohort = CohortFilter.create(label=label, team_codes=['WPW', 'WPM'], uid=test_uid) assert cohort and 'id' in cohort id_of_created_cohort = cohort['id'] # Verify deletion response = client.delete('/api/cohort/delete/{}'.format(id_of_created_cohort)) assert response.status_code == 200 cohorts = CohortFilter.all_owned_by(test_uid) assert not next((c for c in cohorts if c['id'] == id_of_created_cohort), None)
def test_delete_cohort_wrong_user(self, client, fake_auth): """Custom cohort deletion is only available to owners.""" cohort = CohortFilter.create(uid=coe_advisor_uid, label='Badminton teams', group_codes=['WWP', 'MWP']) assert cohort # This user does not own the custom cohort above fake_auth.login('2040') response = client.get(f'/api/filtered_cohort/{cohort.id}') assert response.status_code == 200 _cohort = json.loads(response.data) assert _cohort['isOwnedByCurrentUser'] is False response = client.delete(f'/api/filtered_cohort/delete/{cohort.id}') assert response.status_code == 400 assert '2040 does not own' in str(response.data)
def main(app): from boac.models.cohort_filter import CohortFilter uid = sys.argv[1] first_name = sys.argv[2] if uid: label = f'{first_name}\'s Students' if first_name else 'My Students' cohort = CohortFilter.create( uid=uid, label=label, advisor_ldap_uid=uid, ) print(f'Cohort created: {cohort}') else: print(f'ERROR: Failed to create cohort') print('\nDone.\n')
def create_cohort(): params = request.get_json() name = get_param(params, 'name', None) filters = get_param(params, 'filters', None) order_by = params.get('orderBy') filter_criteria = _filters_to_filter_criteria(filters, order_by) if not name or not filter_criteria: raise BadRequestError( 'Cohort creation requires \'name\' and \'filters\'') cohort = CohortFilter.create( uid=current_user.get_uid(), name=name, filter_criteria=filter_criteria, order_by=order_by, include_alerts_for_user_id=current_user.get_id(), ) _decorate_cohort(cohort) return tolerant_jsonify(cohort)
def test_create_and_delete_cohort(self): """Cohort_filter record to Flask-Login for recognized UID.""" owner = AuthorizedUser.find_by_uid(asc_advisor_uid).uid shared_with = AuthorizedUser.find_by_uid(coe_advisor_uid).uid # Check validity of UIDs assert owner assert shared_with # Create and share cohort group_codes = ['MFB-DB', 'MFB-DL', 'MFB-MLB', 'MFB-OLB'] cohort = CohortFilter.create(uid=owner, label='Football, Defense', group_codes=group_codes) cohort = CohortFilter.share(cohort.id, shared_with) assert len(cohort.owners) == 2 assert owner, shared_with in [user.uid for user in cohort.owners] # Delete cohort and verify previous_owner_count = cohort_count(owner) previous_shared_count = cohort_count(shared_with) CohortFilter.delete(cohort.id) assert cohort_count(owner) == previous_owner_count - 1 assert cohort_count(shared_with) == previous_shared_count - 1
def test_cohort_update_name(self, client, asc_advisor_session): cohort = CohortFilter.create(uid=asc_advisor_uid, label='Swimming, Men\'s', group_codes=['MSW', 'MSW-DV', 'MSW-SW']) updated_label = 'Splashing, Men\'s' # First, we POST an empty label response = client.post('/api/filtered_cohort/update', data=json.dumps({'id': cohort.id}), content_type='application/json') assert 400 == response.status_code # Now, we POST a valid label data = { 'id': cohort.id, 'label': updated_label, } response = client.post('/api/filtered_cohort/update', data=json.dumps(data), content_type='application/json') assert 200 == response.status_code update = response.json assert update['label'] == updated_label def remove_empties(filter_criteria): return {k: v for k, v in filter_criteria.items() if v is not None} expected = remove_empties(cohort.filter_criteria) actual = remove_empties(update['filterCriteria']) assert expected == actual
def test_create_and_delete_cohort(self): """cohort_filter record to Flask-Login for recognized UID""" owner = AuthorizedUser.find_by_uid('2040') shared_with = AuthorizedUser.find_by_uid('1133399') # Check validity of UIDs assert owner assert shared_with # Create and share cohort cohort = CohortFilter.create(label='High-risk Badminton', team_codes=['MBK', 'WBK'], uid=owner.uid) cohort = CohortFilter.share(cohort['id'], shared_with.uid) assert len(cohort['owners']) == 2 assert owner, shared_with in cohort['owners'] # Delete cohort and verify previous_owner_count = cohort_count(owner) previous_shared_count = cohort_count(shared_with) CohortFilter.delete(cohort['id']) assert cohort_count(owner) == previous_owner_count - 1 assert cohort_count(shared_with) == previous_shared_count - 1
def test_ce3_filter_criteria(self): colleges = ['College of Letters and Science', 'College of Engineering'] family_dependent_ranges = [ { 'min': 0, 'max': 2 }, { 'min': 5, 'max': 5 }, ] freshman_or_transfer = ['Transfer'] has_fee_waiver = True cohort = CohortFilter.create( uid=ce3_advisor_uid, name='All my admits', filter_criteria={ 'colleges': colleges, 'familyDependentRanges': family_dependent_ranges, 'freshmanOrTransfer': freshman_or_transfer, 'hasFeeWaiver': has_fee_waiver, }, domain='admitted_students', ) cohort_id = cohort['id'] cohort = CohortFilter.find_by_id(cohort_id) expected = { 'colleges': colleges, 'familyDependentRanges': family_dependent_ranges, 'freshmanOrTransfer': freshman_or_transfer, 'hasFeeWaiver': has_fee_waiver, } for key, value in expected.items(): assert cohort['criteria'][key] == expected[key] assert cohort['totalStudentCount'] == len( CohortFilter.get_sids(cohort_id)) assert cohort['students']
def create_filtered_cohorts(): # Oliver's cohorts CohortFilter.create(uid='2040', label='All sports', group_codes=['MFB-DL', 'WFH']) CohortFilter.create(uid='2040', label='Football, Defense', group_codes=['MFB-DB', 'MFB-DL']) CohortFilter.create(uid='2040', label='Field Hockey', group_codes=['WFH']) # Flint's cohorts asc_advisor_uid = '1081940' CohortFilter.create(uid=asc_advisor_uid, label='Defense Backs, Inactive', group_codes=['MFB-DB'], is_inactive_asc=True) CohortFilter.create(uid=asc_advisor_uid, label='Defense Backs, Active', group_codes=['MFB-DB'], is_inactive_asc=False) CohortFilter.create(uid=asc_advisor_uid, label='Defense Backs, All', group_codes=['MFB-DB']) CohortFilter.create(uid=asc_advisor_uid, label='Undeclared students', majors=['Undeclared'], is_inactive_asc=False) CohortFilter.create(uid=asc_advisor_uid, label='All sports', group_codes=['MFB-DL', 'WFH'], is_inactive_asc=False) # Sandeep's cohorts coe_advisor_uid = '1133399' CohortFilter.create(uid=coe_advisor_uid, label='Sandeep\'s Students', advisor_ldap_uids=[coe_advisor_uid]) CohortFilter.create(uid='1133399', label='Radioactive Women and Men', majors=['Nuclear Engineering BS']) std_commit(allow_test_environment=True)
def create_cohort(team_code1, team_code2, uid): name1 = TeamMember.team_definitions[team_code1] name2 = TeamMember.team_definitions[team_code2] CohortFilter.create(label=name1 + ' and ' + name2, team_codes=[team_code1, team_code2], uid=uid)
def _create_cohorts(): # Oliver's cohorts CohortFilter.create( uid='2040', name='All sports', filter_criteria={ 'groupCodes': ['MFB-DL', 'WFH'], }, ) CohortFilter.create( uid='2040', name='Football, Defense', filter_criteria={ 'groupCodes': ['MFB-DB', 'MFB-DL'], }, ) CohortFilter.create( uid='2040', name='Field Hockey', filter_criteria={ 'groupCodes': ['WFH'], }, ) # Flint's cohorts asc_advisor_uid = '1081940' CohortFilter.create( uid=asc_advisor_uid, name='Defense Backs, Inactive', filter_criteria={ 'groupCodes': ['MFB-DB'], 'isInactiveAsc': True, }, ) CohortFilter.create( uid=asc_advisor_uid, name='Defense Backs, Active', filter_criteria={ 'groupCodes': ['MFB-DB'], 'isInactiveAsc': False, }, ) CohortFilter.create( uid=asc_advisor_uid, name='Defense Backs, All', filter_criteria={ 'groupCodes': ['MFB-DB'], }, ) CohortFilter.create( uid=asc_advisor_uid, name='Undeclared students', filter_criteria={ 'majors': ['Undeclared'], 'isInactiveAsc': False, }, ) CohortFilter.create( uid=asc_advisor_uid, name='All sports', filter_criteria={ 'groupCodes': ['MFB-DL', 'WFH'], 'isInactiveAsc': False, }, ) coe_advisor_uid = '1133399' CohortFilter.create( uid=coe_advisor_uid, name='Roberta\'s Students', filter_criteria={ 'coeAdvisorLdapUids': [coe_advisor_uid], }, ) CohortFilter.create( uid=coe_advisor_uid, name='Radioactive Women and Men', filter_criteria={ 'majors': ['Nuclear Engineering BS'], }, ) # The CE3 advisor will create a standard cohort and a cohort with domain='admitted_students' ce3_advisor_uid = '2525' CohortFilter.create( uid=ce3_advisor_uid, name='Undeclared students', filter_criteria={ 'majors': ['Undeclared'], 'isInactiveAsc': False, }, ) CohortFilter.create( uid=ce3_advisor_uid, name='First Generation Students', filter_criteria={ 'isFirstGenerationCollege': True, }, domain='admitted_students', ) std_commit(allow_test_environment=True)