Ejemplo n.º 1
0
def get_students_with_alerts(curated_group_id):
    offset = get_param(request.args, 'offset', 0)
    limit = get_param(request.args, 'limit', 50)
    benchmark = get_benchmarker(
        f'curated group {curated_group_id} students_with_alerts')
    benchmark('begin')
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    if not curated_group:
        raise ResourceNotFoundError(
            f'Sorry, no curated group found with id {curated_group_id}.')
    if not _can_current_user_view_curated_group(curated_group):
        raise ForbiddenRequestError(
            f'Current user, {current_user.get_uid()}, cannot view curated group {curated_group.id}'
        )
    students = Alert.include_alert_counts_for_students(
        benchmark=benchmark,
        viewer_user_id=current_user.get_id(),
        group={'sids': CuratedGroup.get_all_sids(curated_group_id)},
        count_only=True,
        offset=offset,
        limit=limit,
    )
    alert_count_per_sid = {}
    for s in list(filter(lambda s: s.get('alertCount') > 0, students)):
        sid = s.get('sid')
        alert_count_per_sid[sid] = s.get('alertCount')
    sids = list(alert_count_per_sid.keys())
    benchmark('begin profile query')
    students_with_alerts = get_student_profile_summaries(sids=sids)
    benchmark('end profile query')
    for student in students_with_alerts:
        student['alertCount'] = alert_count_per_sid[student['sid']]
    benchmark('end')
    return tolerant_jsonify(students_with_alerts)
Ejemplo n.º 2
0
def _get_curated_groups_ids_and_sids(advisor):
    sids = []
    curated_group_ids = []
    for curated_group in CuratedGroup.get_curated_groups_by_owner_id(advisor.id):
        curated_group_ids.append(curated_group.id)
        sids = sids + CuratedGroup.get_all_sids(curated_group.id)
    return curated_group_ids, sids
Ejemplo n.º 3
0
    def test_distinct_sids(self, client, fake_auth):
        """Get distinct SIDs across cohorts and curated groups."""
        user_id = AuthorizedUser.get_id_per_uid(coe_advisor_uid)
        cohort_ids = []
        sids = set()
        for cohort in CohortFilter.get_cohorts(user_id):
            cohort_id = cohort['id']
            cohort_ids.append(cohort_id)
            sids.update(set(CohortFilter.get_sids(cohort_id)))

        assert len(sids) > 1
        curated_group = CuratedGroup.create(
            user_id, 'Like a lemon to a lime, a lime to a lemon')
        curated_group_ids = [curated_group.id]
        # We use SIDs from cohorts (above). Therefore, we expect no increase in 'batch_distinct_student_count'.
        for sid in sids:
            CuratedGroup.add_student(curated_group.id, sid)
        # A specific student (SID) that is in neither cohorts nor curated groups.
        some_other_sid = '5678901234'
        assert some_other_sid not in sids
        # Log in as authorized user
        fake_auth.login(coe_advisor_uid)
        data = self._api_distinct_sids(
            client,
            cohort_ids=cohort_ids,
            curated_group_ids=curated_group_ids,
            sids=[some_other_sid],
        )
        assert sids.union({some_other_sid}) == set(data['sids'])
Ejemplo n.º 4
0
def remove_student_from_curated_group(curated_group_id, sid):
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    if not curated_group:
        raise ResourceNotFoundError(
            f'No curated group found with id: {curated_group_id}')
    if curated_group.owner_id != current_user.get_id():
        raise ForbiddenRequestError(
            f'Current user, {current_user.get_uid()}, does not own curated group {curated_group.id}'
        )
    CuratedGroup.remove_student(curated_group_id, sid)
    return tolerant_jsonify(curated_group.to_api_json(include_students=False))
Ejemplo n.º 5
0
def create_curated_group():
    params = request.get_json()
    name = params.get('name', None)
    if not name:
        raise BadRequestError('Curated group creation requires \'name\'')
    curated_group = CuratedGroup.create(current_user.get_id(), name)
    # Optionally, add students
    if 'sids' in params:
        sids = [sid for sid in set(params.get('sids')) if sid.isdigit()]
        CuratedGroup.add_students(curated_group_id=curated_group.id, sids=sids)
    return tolerant_jsonify(curated_group.to_api_json())
Ejemplo n.º 6
0
def update_curated_group_lists():
    """Remove no-longer-accessible students from curated group lists."""
    from boac.models.curated_group import CuratedGroup
    for curated_group in CuratedGroup.query.all():
        all_sids = CuratedGroupStudent.get_sids(curated_group.id)
        available_students = [s['sid'] for s in data_loch.get_student_profiles(all_sids)]
        if len(all_sids) > len(available_students):
            unavailable_sids = set(all_sids) - set(available_students)
            app.logger.info(f'Deleting inaccessible SIDs from curated group {curated_group.id}: {unavailable_sids}')
            for sid in unavailable_sids:
                CuratedGroup.remove_student(curated_group.id, sid)
Ejemplo n.º 7
0
def delete_curated_group(curated_group_id):
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    if not curated_group:
        raise ResourceNotFoundError(
            f'No curated group found with id: {curated_group_id}')
    if curated_group.owner_id != current_user.get_id():
        raise ForbiddenRequestError(
            f'Current user, {current_user.get_uid()}, does not own curated group {curated_group.id}'
        )
    CuratedGroup.delete(curated_group_id)
    return tolerant_jsonify(
        {'message': f'Curated group {curated_group_id} has been deleted'}), 200
Ejemplo n.º 8
0
def download_csv(curated_group_id):
    benchmark = get_benchmarker(
        f'curated group {curated_group_id} download_csv')
    benchmark('begin')
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    if not curated_group:
        raise ResourceNotFoundError(
            f'No curated group found with id: {curated_group_id}')
    if curated_group.owner_id != current_user.get_id():
        raise ForbiddenRequestError(
            f'Current user, {current_user.get_uid()}, does not own curated group {curated_group.id}'
        )
    return response_with_students_csv_download(
        sids=CuratedGroup.get_all_sids(curated_group_id), benchmark=benchmark)
Ejemplo n.º 9
0
def rename_curated_group():
    params = request.get_json()
    name = params['name']
    if not name:
        raise BadRequestError(
            'Requested curated group name is empty or invalid')
    curated_group_id = params['id']
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    if not curated_group or curated_group.owner_id != current_user.get_id():
        raise BadRequestError(
            'Curated group does not exist or is not available to you')
    CuratedGroup.rename(curated_group_id=curated_group.id, name=name)
    return tolerant_jsonify(
        CuratedGroup.find_by_id(curated_group_id).to_api_json())
Ejemplo n.º 10
0
def get_my_curated_groups():
    curated_groups = []
    user_id = current_user.get_id()
    for curated_group in CuratedGroup.get_curated_groups_by_owner_id(user_id):
        api_json = curated_group.to_api_json(include_students=False)
        students = [{'sid': sid} for sid in CuratedGroup.get_all_sids(curated_group.id)]
        students_with_alerts = Alert.include_alert_counts_for_students(
            viewer_user_id=user_id,
            group={'students': students},
            count_only=True,
        )
        api_json['alertCount'] = sum(s['alertCount'] for s in students_with_alerts)
        api_json['totalStudentCount'] = len(students)
        curated_groups.append(api_json)
    return curated_groups
Ejemplo n.º 11
0
def _curated_group_with_complete_student_profiles(curated_group_id,
                                                  order_by='last_name',
                                                  offset=0,
                                                  limit=50):
    benchmark = get_benchmarker(
        f'curated group {curated_group_id} with student profiles')
    benchmark('begin')
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    if not curated_group:
        raise ResourceNotFoundError(
            f'Sorry, no curated group found with id {curated_group_id}.')
    if curated_group.owner_id != current_user.get_id():
        raise ForbiddenRequestError(
            f'Current user, {current_user.get_uid()}, does not own curated group {curated_group.id}'
        )
    api_json = curated_group.to_api_json(order_by=order_by,
                                         offset=offset,
                                         limit=limit)
    sids = [s['sid'] for s in api_json['students']]
    benchmark('begin profile query')
    api_json['students'] = get_summary_student_profiles(sids)
    benchmark('begin alerts query')
    Alert.include_alert_counts_for_students(
        viewer_user_id=current_user.get_id(), group=api_json)
    benchmark('end')
    return api_json
Ejemplo n.º 12
0
def _curated_group_with_complete_student_profiles(curated_group_id,
                                                  order_by='last_name',
                                                  term_id=None,
                                                  offset=0,
                                                  limit=50):
    benchmark = get_benchmarker(
        f'curated group {curated_group_id} with student profiles')
    benchmark('begin')
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    if not curated_group:
        raise ResourceNotFoundError(
            f'Sorry, no curated group found with id {curated_group_id}.')
    if not _can_current_user_view_curated_group(curated_group):
        raise ForbiddenRequestError(
            f'Current user, {current_user.get_uid()}, cannot view curated group {curated_group.id}'
        )
    api_json = curated_group.to_api_json(order_by=order_by,
                                         offset=offset,
                                         limit=limit)
    sids = [s['sid'] for s in api_json['students']]
    benchmark('begin profile query')
    api_json['students'] = get_summary_student_profiles(
        sids, term_id=term_id, include_historical=True)
    benchmark('begin alerts query')
    Alert.include_alert_counts_for_students(
        viewer_user_id=current_user.get_id(), group=api_json)
    benchmark('end')
    benchmark('begin get_referencing_cohort_ids')
    api_json[
        'referencingCohortIds'] = curated_group.get_referencing_cohort_ids()
    benchmark('end')
    return api_json
Ejemplo n.º 13
0
def create_curated_group():
    params = request.get_json()
    domain = get_param(params, 'domain', 'default')
    if is_unauthorized_domain(domain):
        raise ForbiddenRequestError(
            f'You are unauthorized to use the \'{domain}\' domain')
    name = params.get('name', None)
    if not name:
        raise BadRequestError('Curated group creation requires \'name\'')
    curated_group = CuratedGroup.create(domain=domain,
                                        name=name,
                                        owner_id=current_user.get_id())
    # Optionally, add students
    if 'sids' in params:
        sids = [sid for sid in set(params.get('sids')) if sid.isdigit()]
        CuratedGroup.add_students(curated_group_id=curated_group.id, sids=sids)
    return tolerant_jsonify(curated_group.to_api_json(include_students=True))
Ejemplo n.º 14
0
 def test_curated_groups_by_sid(self, client, coe_advisor,
                                coe_advisor_groups):
     """API delivers accurate set of student SIDs."""
     sids = CuratedGroup.get_all_sids(
         curated_group_id=coe_advisor_groups[0].id)
     sample_sid = sids[0]
     assert self._api_my_curated_groups_by_sid(
         client, sid=sample_sid) == [coe_advisor_groups[0].id]
Ejemplo n.º 15
0
def download_csv(curated_group_id):
    benchmark = get_benchmarker(
        f'curated group {curated_group_id} download_csv')
    benchmark('begin')
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    params = request.get_json()
    fieldnames = get_param(params, 'csvColumnsSelected', [])
    if not curated_group:
        raise ResourceNotFoundError(
            f'No curated group found with id: {curated_group_id}')
    if not _can_current_user_view_curated_group(curated_group):
        raise ForbiddenRequestError(
            f'Current user, {current_user.get_uid()}, cannot view curated group {curated_group.id}'
        )
    return response_with_students_csv_download(
        sids=CuratedGroup.get_all_sids(curated_group_id),
        fieldnames=fieldnames,
        benchmark=benchmark)
Ejemplo n.º 16
0
    def test_update_curated_group_lists(self, app):
        from boac.api.cache_utils import update_curated_group_lists
        curated_group = CuratedGroup.create(
            owner_id=AuthorizedUser.find_by_uid('6446').id,
            name='This group has one student not in Data Loch',
        )
        original_sids = ['3456789012', '5678901234', '7890123456']
        for sid in original_sids:
            CuratedGroup.add_student(curated_group.id, sid)
        sid_not_in_data_loch = '19040616'
        CuratedGroup.add_student(curated_group.id, sid_not_in_data_loch)
        std_commit(allow_test_environment=True)

        revised_sids = CuratedGroupStudent.get_sids(curated_group.id)
        assert sid_not_in_data_loch in revised_sids
        update_curated_group_lists()
        std_commit(allow_test_environment=True)

        final_sids = CuratedGroupStudent.get_sids(curated_group.id)
        assert sid_not_in_data_loch not in final_sids
        assert set(final_sids) == set(original_sids)
Ejemplo n.º 17
0
def get_my_curated_groups():
    benchmark = get_benchmarker('my_curated_groups')
    curated_groups = []
    user_id = current_user.get_id()
    for curated_group in CuratedGroup.get_curated_groups(owner_id=user_id):
        students = [{
            'sid': sid
        } for sid in CuratedGroup.get_all_sids(curated_group.id)]
        students_with_alerts = Alert.include_alert_counts_for_students(
            benchmark=benchmark,
            viewer_user_id=user_id,
            group={'students': students},
            count_only=True,
        )
        curated_groups.append({
            **curated_group.to_api_json(include_students=False),
            'alertCount':
            sum(s['alertCount'] for s in students_with_alerts),
            'sids': [student['sid'] for student in students],
            'totalStudentCount':
            len(students),
        })
    return curated_groups
Ejemplo n.º 18
0
def add_students_to_curated_group():
    params = request.get_json()
    curated_group_id = params.get('curatedGroupId')
    return_student_profiles = params.get('returnStudentProfiles')
    sids = [sid for sid in set(params.get('sids')) if sid.isdigit()]
    if not curated_group_id or not len(sids):
        raise BadRequestError(
            'The required parameters are \'curatedGroupId\' and \'sids\'.')
    curated_group = CuratedGroup.find_by_id(curated_group_id)
    if not curated_group:
        raise ResourceNotFoundError(
            f'No curated group found where id={curated_group_id}')
    if curated_group.owner_id != current_user.get_id():
        raise ForbiddenRequestError(
            f'Current user, {current_user.get_uid()}, does not own curated group {curated_group.id}'
        )
    CuratedGroup.add_students(curated_group_id=curated_group_id, sids=sids)
    if return_student_profiles:
        return tolerant_jsonify(
            _curated_group_with_complete_student_profiles(
                curated_group_id=curated_group_id))
    else:
        group = CuratedGroup.find_by_id(curated_group_id)
        return tolerant_jsonify(group.to_api_json(include_students=False))
Ejemplo n.º 19
0
def all_curated_groups():
    scope = get_query_scope(current_user)
    uids = AuthorizedUser.get_all_uids_in_scope(scope)
    groups_per_uid = dict((uid, []) for uid in uids)
    for group in CuratedGroup.get_groups_owned_by_uids(uids=uids):
        groups_per_uid[group['ownerUid']].append(group)
    api_json = []
    for uid, user in calnet.get_calnet_users_for_uids(app, uids).items():
        groups = groups_per_uid[uid]
        api_json.append({
            'user': user,
            'groups': sorted(groups, key=lambda g: g['name']),
        })
    api_json = sorted(
        api_json,
        key=lambda v: v['user']['name'] or f"UID: {v['user']['uid']}")
    return tolerant_jsonify(api_json)
def admin_curated_groups():
    user = AuthorizedUser.find_by_uid(admin_uid)
    return CuratedGroup.get_curated_groups_by_owner_id(user.id)
def asc_curated_groups():
    advisor = AuthorizedUser.find_by_uid(asc_advisor_uid)
    return CuratedGroup.get_curated_groups(advisor.id)
Ejemplo n.º 22
0
def curated_group_ids_per_sid(sid):
    return tolerant_jsonify(
        CuratedGroup.curated_group_ids_per_sid(user_id=current_user.get_id(),
                                               sid=sid))
def coe_advisor_groups():
    advisor = AuthorizedUser.find_by_uid(coe_advisor_uid)
    return CuratedGroup.get_curated_groups_by_owner_id(advisor.id)
Ejemplo n.º 24
0
def _create_curated_groups():
    admin_user = AuthorizedUser.find_by_uid('2040')
    CuratedGroup.create(admin_user.id, 'My Students')

    asc_advisor = AuthorizedUser.find_by_uid('6446')
    CuratedGroup.create(asc_advisor.id, 'My Students')

    curated_group = CuratedGroup.create(asc_advisor.id, 'Four students')
    CuratedGroup.add_student(curated_group.id, '3456789012')
    CuratedGroup.add_student(curated_group.id, '5678901234')
    CuratedGroup.add_student(curated_group.id, '11667051')
    CuratedGroup.add_student(curated_group.id, '7890123456')

    coe_advisor = AuthorizedUser.find_by_uid('1133399')
    curated_group = CuratedGroup.create(coe_advisor.id, 'I have one student')
    CuratedGroup.add_student(curated_group.id, '7890123456')
    std_commit(allow_test_environment=True)
Ejemplo n.º 25
0
def _get_sids_per_curated_groups(curated_group_ids=None):
    sids = set()
    for curated_group_id in curated_group_ids or ():
        if curated_group_id:
            sids = sids.union(CuratedGroup.get_all_sids(curated_group_id))
    return sids