Пример #1
0
def update_cohort():
    params = request.get_json()
    cohort_id = int(params.get('id'))
    name = params.get('name')
    filters = params.get('filters')
    # Validation
    if not name and not filters:
        raise BadRequestError('Invalid request')
    if not CohortFilter.is_cohort_owned_by(cohort_id, current_user.get_id()):
        raise ForbiddenRequestError(f'Invalid or unauthorized request')
    filter_keys = list(map(lambda f: f['key'], filters))
    if is_unauthorized_search(filter_keys):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    filter_criteria = _translate_filters_to_cohort_criteria(filters)
    updated = CohortFilter.update(
        cohort_id=cohort_id,
        name=name,
        filter_criteria=filter_criteria,
        include_students=False,
        include_alerts_for_user_id=current_user.get_id(),
    )
    _decorate_cohort(updated)
    return tolerant_jsonify(updated)
Пример #2
0
def download_csv_per_filters():
    benchmark = get_benchmarker('cohort download_csv_per_filters')
    benchmark('begin')
    params = request.get_json()
    filters = get_param(params, 'filters', [])
    fieldnames = get_param(params, 'csvColumnsSelected', [])
    domain = get_param(params, 'domain', 'default')
    if (domain == 'default' and not filters) or filters is None:
        raise BadRequestError('API requires \'filters\'')
    filter_keys = list(map(lambda f: f['key'], filters))
    if is_unauthorized_search(filter_keys):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    domain = get_param(params, 'domain', 'default')
    if is_unauthorized_domain(domain):
        raise ForbiddenRequestError(
            f'You are unauthorized to query the \'{domain}\' domain')
    cohort = _construct_phantom_cohort(
        domain=domain,
        filters=filters,
        offset=0,
        limit=None,
        include_profiles=False,
        include_sids=True,
        include_students=False,
    )
    return _response_with_csv_download(benchmark, domain, fieldnames,
                                       cohort['sids'])
Пример #3
0
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)
Пример #4
0
def update_note():
    params = request.form
    body = params.get('body', None)
    is_private = to_bool_or_none(params.get('isPrivate', False))
    note_id = params.get('id', None)
    subject = params.get('subject', None)
    topics = get_note_topics_from_http_post()

    note = Note.find_by_id(note_id=note_id) if note_id else None
    if not note:
        raise ResourceNotFoundError('Note not found')
    if not subject:
        raise BadRequestError('Note subject is required')
    if note.author_uid != current_user.get_uid():
        raise ForbiddenRequestError(
            'Sorry, you are not the author of this note.')
    if (is_private is not note.is_private
        ) and not current_user.can_access_private_notes:
        raise ForbiddenRequestError(
            'Sorry, you are not authorized to manage note privacy')

    note = Note.update(
        body=process_input_from_rich_text_editor(body),
        is_private=is_private,
        note_id=note_id,
        subject=subject,
        topics=topics,
    )
    note_read = NoteRead.find_or_create(current_user.get_id(), note_id)
    return tolerant_jsonify(
        _boa_note_to_compatible_json(note=note, note_read=note_read))
Пример #5
0
def create_notes():
    benchmark = get_benchmarker('create_notes')
    params = request.form
    sids = _get_sids_for_note_creation()
    benchmark(f'SID count: {len(sids)}')
    body = params.get('body', None)
    is_private = to_bool_or_none(params.get('isPrivate', False))
    subject = params.get('subject', None)
    topics = get_note_topics_from_http_post()
    if not sids or not subject:
        benchmark('end (BadRequest)')
        raise BadRequestError(
            'Note creation requires \'subject\' and \'sids\'')

    dept_codes = dept_codes_where_advising(current_user)
    if current_user.is_admin or not len(dept_codes):
        benchmark('end (Forbidden)')
        raise ForbiddenRequestError(
            'Sorry, only advisors can create advising notes')
    if is_private and not current_user.can_access_private_notes:
        benchmark('end (Forbidden)')
        raise ForbiddenRequestError(
            'Sorry, you are not authorized to manage note privacy.')

    attachments = get_note_attachments_from_http_post(tolerate_none=True)
    benchmark(f'Attachment count: {len(attachments)}')
    body = process_input_from_rich_text_editor(body)
    template_attachment_ids = get_template_attachment_ids_from_http_post()

    if len(sids) == 1:
        note = Note.create(
            **_get_author_profile(),
            attachments=attachments,
            body=body,
            is_private=is_private,
            sid=sids[0],
            subject=subject,
            template_attachment_ids=template_attachment_ids,
            topics=topics,
        )
        response = tolerant_jsonify(
            _boa_note_to_compatible_json(note, note_read=True))
    else:
        response = tolerant_jsonify(
            Note.create_batch(
                **_get_author_profile(),
                attachments=attachments,
                author_id=current_user.to_api_json()['id'],
                body=body,
                is_private=is_private,
                sids=sids,
                subject=subject,
                template_attachment_ids=template_attachment_ids,
                topics=topics,
            ), )
    benchmark('end')
    return response
Пример #6
0
def get_waitlist(dept_code):
    def _is_current_user_authorized():
        return current_user.is_admin or dept_code in _dept_codes_with_scheduler_privilege()

    dept_code = dept_code.upper()
    if dept_code not in BERKELEY_DEPT_CODE_TO_NAME:
        raise ResourceNotFoundError(f'Unrecognized department code: {dept_code}')
    elif _is_current_user_authorized():
        show_all_statuses = current_user.is_drop_in_advisor or current_user.is_admin
        statuses = appointment_event_type.enums if show_all_statuses else ['reserved', 'waiting']
        unresolved = []
        resolved = []
        for appointment in Appointment.get_drop_in_waitlist(dept_code, statuses):
            a = appointment.to_api_json(current_user.get_id())
            if a['status'] in ['reserved', 'waiting']:
                unresolved.append(a)
            else:
                resolved.append(a)
        _put_student_profile_per_appointment(unresolved)
        _put_student_profile_per_appointment(resolved)
        return tolerant_jsonify({
            'advisors': drop_in_advisors_for_dept_code(dept_code),
            'waitlist': {
                'unresolved': unresolved,
                'resolved': resolved,
            },
        })
    else:
        raise ForbiddenRequestError(f'You are unauthorized to manage {dept_code} appointments.')
Пример #7
0
def update_appointment(appointment_id):
    appointment = Appointment.find_by_id(appointment_id)
    if not appointment:
        raise ResourceNotFoundError('Unknown path')
    has_privilege = current_user.is_admin or appointment.dept_code in _dept_codes_with_scheduler_privilege()
    if not has_privilege:
        raise ForbiddenRequestError(f'You are unauthorized to manage {appointment.dept_code} appointments.')
    params = request.get_json()
    details = params.get('details', None)
    scheduled_time = params.get('scheduledTime', None)
    if scheduled_time:
        scheduled_time = localized_timestamp_to_utc(scheduled_time)
    student_contact_info = params.get('studentContactInfo', None)
    student_contact_type = params.get('studentContactType', None)
    topics = params.get('topics', None)
    appointment.update(
        details=process_input_from_rich_text_editor(details),
        scheduled_time=scheduled_time,
        student_contact_info=student_contact_info,
        student_contact_type=student_contact_type,
        topics=topics,
        updated_by=current_user.get_id(),
    )
    api_json = appointment.to_api_json(current_user.get_id())
    _put_student_profile_per_appointment([api_json])
    return tolerant_jsonify(api_json)
Пример #8
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
Пример #9
0
def validate_sids():
    params = request.get_json()
    sids = [sid.strip() for sid in list(params.get('sids'))]
    domain = params.get('domain') or 'default'
    if is_unauthorized_domain(domain):
        raise ForbiddenRequestError(
            f'You are unauthorized to query the \'{domain}\' domain')
    if sids:
        if next((sid for sid in sids if not sid.isnumeric()), None):
            raise BadRequestError('Each SID must be numeric')
        else:
            summary = []
            if domain == 'admitted_students':
                available_sids = [
                    row['sid']
                    for row in get_admitted_students_by_sids(offset=0,
                                                             sids=sids)
                ]
            else:
                available_sids = query_students(
                    sids=sids, sids_only=True,
                    academic_career_status=('all'))['sids']
            for sid in sids:
                summary.append({
                    'sid': sid,
                    'status': 200 if sid in available_sids else 404,
                })
            return tolerant_jsonify(summary)
    else:
        raise BadRequestError('Requires \'sids\' param')
Пример #10
0
def search():
    params = util.remove_none_values(request.get_json())
    order_by = util.get(params, 'orderBy', None)
    if is_unauthorized_search(list(params.keys()), order_by):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    search_phrase = util.get(params, 'searchPhrase', '').strip()
    domain = {
        'students': util.get(params, 'students'),
        'courses': util.get(params, 'courses'),
        'notes': util.get(params, 'notes'),
    }
    if not domain['students'] and not domain['courses'] and not domain['notes']:
        raise BadRequestError('No search domain specified')
    if not len(search_phrase) and not domain['notes']:
        raise BadRequestError('Invalid or empty search input')

    feed = {}

    if len(search_phrase) and domain['students']:
        feed.update(_student_search(search_phrase, params, order_by))

    if len(search_phrase) and domain['courses']:
        feed.update(_course_search(search_phrase, params, order_by))

    if domain['notes']:
        feed.update(_notes_search(search_phrase, params))

    return tolerant_jsonify(feed)
Пример #11
0
def _filters_to_filter_criteria(filters, order_by=None):
    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'
        )
    return CohortFilter.translate_filters_to_cohort_criteria(filters)
Пример #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
Пример #13
0
def get_cohort(cohort_id):
    benchmark = get_benchmarker(f'cohort {cohort_id} get_cohort')
    benchmark('begin')
    filter_keys = list(request.args.keys())
    order_by = get_param(request.args, 'orderBy', None)
    if is_unauthorized_search(filter_keys, order_by):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    include_students = to_bool(get_param(request.args, 'includeStudents'))
    include_students = True if include_students is None else include_students
    offset = get_param(request.args, 'offset', 0)
    limit = get_param(request.args, 'limit', 50)
    benchmark('begin cohort filter query')
    cohort = CohortFilter.find_by_id(
        int(cohort_id),
        order_by=order_by,
        offset=int(offset),
        limit=int(limit),
        include_alerts_for_user_id=current_user.get_id(),
        include_profiles=True,
        include_students=include_students,
    )
    if cohort and _can_current_user_view_cohort(cohort):
        _decorate_cohort(cohort)
        benchmark('end')
        return tolerant_jsonify(cohort)
    else:
        raise ResourceNotFoundError(
            f'No cohort found with identifier: {cohort_id}')
Пример #14
0
def get_note_template(note_template_id):
    note_template = NoteTemplate.find_by_id(note_template_id=note_template_id)
    if not note_template:
        raise ResourceNotFoundError('Template not found')
    if note_template.creator_id != current_user.get_id():
        raise ForbiddenRequestError('Template not available')
    return tolerant_jsonify(note_template.to_api_json())
Пример #15
0
def batch_create_notes():
    params = request.form
    sids = _get_sids_for_note_creation()
    subject = params.get('subject', None)
    body = params.get('body', None)
    topics = get_note_topics_from_http_post()
    if not sids or not subject:
        raise BadRequestError('Note creation requires \'subject\' and \'sid\'')
    user_dept_codes = dept_codes_where_advising(current_user)
    if current_user.is_admin or not len(user_dept_codes):
        raise ForbiddenRequestError(
            'Sorry, only advisors can create advising notes')

    author_profile = _get_author_profile()
    attachments = get_note_attachments_from_http_post(tolerate_none=True)

    note_ids_per_sid = Note.create_batch(
        author_id=current_user.to_api_json()['id'],
        **author_profile,
        subject=subject,
        body=process_input_from_rich_text_editor(body),
        topics=topics,
        sids=sids,
        attachments=attachments,
        template_attachment_ids=get_template_attachment_ids_from_http_post(),
    )
    return tolerant_jsonify(note_ids_per_sid)
Пример #16
0
def search_students():
    params = request.get_json()
    if is_unauthorized_search(params):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    search_phrase = util.get(params, 'searchPhrase', '').strip()
    if not len(search_phrase):
        raise BadRequestError('Invalid or empty search input')
    results = search_for_students(
        include_profiles=True,
        search_phrase=search_phrase.replace(',', ' '),
        is_active_asc=_convert_asc_inactive_arg(
            util.get(params, 'isInactiveAsc')),
        order_by=util.get(params, 'orderBy', None),
        offset=util.get(params, 'offset', 0),
        limit=util.get(params, 'limit', 50),
    )
    alert_counts = Alert.current_alert_counts_for_viewer(current_user.id)
    students = results['students']
    add_alert_counts(alert_counts, students)
    return tolerant_jsonify({
        'students': students,
        'totalStudentCount': results['totalStudentCount'],
    })
Пример #17
0
def create_note_template():
    params = request.form
    title = params.get('title', None)
    subject = params.get('subject', None)
    body = params.get('body', None)
    topics = get_note_topics_from_http_post()
    if not title or not subject:
        raise BadRequestError(
            'Note creation requires \'subject\' and \'title\'')
    user_dept_codes = dept_codes_where_advising(current_user)
    if current_user.is_admin or not len(user_dept_codes):
        raise ForbiddenRequestError(
            'Sorry, only advisors can create advising note templates')

    attachments = get_note_attachments_from_http_post(tolerate_none=True)

    note_template = NoteTemplate.create(
        attachments=attachments,
        body=process_input_from_rich_text_editor(body),
        creator_id=current_user.get_id(),
        is_private=to_bool_or_none(params.get('isPrivate', False)),
        subject=subject,
        title=title,
        topics=topics,
    )
    return tolerant_jsonify(note_template.to_api_json())
Пример #18
0
def update_note_template():
    params = request.form
    note_template_id = params.get('id', None)
    subject = params.get('subject', None)
    if not subject:
        raise BadRequestError('Requires \'subject\'')
    body = params.get('body', None)
    topics = get_note_topics_from_http_post()
    delete_ids_ = params.get('deleteAttachmentIds') or []
    delete_ids_ = delete_ids_ if isinstance(
        delete_ids_, list) else str(delete_ids_).split(',')
    delete_attachment_ids = [int(id_) for id_ in delete_ids_]
    note_template = NoteTemplate.find_by_id(note_template_id=note_template_id)
    if not note_template:
        raise ResourceNotFoundError('Template not found')
    if note_template.creator_id != current_user.get_id():
        raise ForbiddenRequestError('Template not available.')
    note_template = NoteTemplate.update(
        attachments=get_note_attachments_from_http_post(tolerate_none=True),
        body=process_input_from_rich_text_editor(body),
        delete_attachment_ids=delete_attachment_ids,
        is_private=to_bool_or_none(params.get('isPrivate', False)),
        note_template_id=note_template_id,
        subject=subject,
        topics=topics,
    )
    return tolerant_jsonify(note_template.to_api_json())
Пример #19
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)
Пример #20
0
def get_cohort(cohort_id):
    if is_unauthorized_search(request.args):
        raise ForbiddenRequestError(
            'You are unauthorized to access student data managed by other departments'
        )
    include_students = util.to_bool_or_none(
        util.get(request.args, 'includeStudents'))
    include_students = True if include_students is None else include_students
    order_by = util.get(request.args, 'orderBy', None)
    offset = util.get(request.args, 'offset', 0)
    limit = util.get(request.args, 'limit', 50)
    cohort = CohortFilter.find_by_id(int(cohort_id))
    if cohort and can_view_cohort(current_user, cohort):
        cohort = decorate_cohort(
            cohort,
            order_by=order_by,
            offset=int(offset),
            limit=int(limit),
            include_alerts_for_uid=current_user.uid,
            include_profiles=True,
            include_students=include_students,
        )
        return tolerant_jsonify(cohort)
    else:
        raise ResourceNotFoundError(
            f'No cohort found with identifier: {cohort_id}')
Пример #21
0
def appointment_check_in(appointment_id):
    appointment = Appointment.find_by_id(appointment_id)
    if not appointment:
        raise ResourceNotFoundError('Unknown path')
    if appointment.dept_code in _dept_codes_with_scheduler_privilege():
        params = request.get_json()
        advisor_uid = params.get('advisorUid', None)
        if not advisor_uid:
            raise BadRequestError(
                'Appointment check-in requires \'advisor_uid\'')
        appointment = Appointment.check_in(
            appointment_id=appointment_id,
            checked_in_by=current_user.get_id(),
            advisor_dept_codes=params.get('advisorDeptCodes', None),
            advisor_name=params.get('advisorName', None),
            advisor_role=params.get('advisorRole', None),
            advisor_uid=advisor_uid,
        )
        api_json = appointment.to_api_json(current_user.get_id())
        _put_student_profile_per_appointment([api_json])
        return tolerant_jsonify(api_json)
    else:
        raise ForbiddenRequestError(
            f'You are unauthorized to manage {appointment.dept_code} appointments.'
        )
Пример #22
0
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))
Пример #23
0
def create_appointment():
    params = request.get_json()
    dept_code = params.get('deptCode', None)
    sid = params.get('sid', None)
    advisor_uid = params.get('advisorUid', None)
    appointment_type = params.get('appointmentType', None)
    topics = params.get('topics', None)
    if not dept_code or not sid or not appointment_type or not len(topics):
        raise BadRequestError(
            'Appointment creation: required parameters were not provided')
    dept_code = dept_code.upper()
    if dept_code not in BERKELEY_DEPT_CODE_TO_NAME:
        raise ResourceNotFoundError(
            f'Unrecognized department code: {dept_code}')
    if dept_code not in _dept_codes_with_scheduler_privilege():
        raise ForbiddenRequestError(
            f'You are unauthorized to manage {dept_code} appointments.')
    appointment = Appointment.create(
        advisor_uid=advisor_uid,
        appointment_type=appointment_type,
        created_by=current_user.get_id(),
        dept_code=dept_code,
        details=params.get('details', None),
        student_sid=sid,
        topics=topics,
    )
    AppointmentRead.find_or_create(current_user.get_id(), appointment.id)
    api_json = appointment.to_api_json(current_user.get_id())
    _put_student_profile_per_appointment([api_json])
    return tolerant_jsonify(api_json)
Пример #24
0
def get_cohort_per_filters():
    benchmark = get_benchmarker('cohort get_students_per_filters')
    benchmark('begin')
    params = request.get_json()
    filters = get_param(params, 'filters', [])
    if not filters:
        raise BadRequestError('API requires \'filters\'')
    include_students = to_bool(get_param(params, 'includeStudents'))
    include_students = True if include_students is None else include_students
    order_by = get_param(params, 'orderBy', None)
    offset = get_param(params, 'offset', 0)
    limit = get_param(params, 'limit', 50)
    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'
        )
    benchmark('begin phantom cohort query')
    cohort = _construct_phantom_cohort(
        filters=filters,
        order_by=order_by,
        offset=int(offset),
        limit=int(limit),
        include_alerts_for_user_id=current_user.get_id(),
        include_profiles=True,
        include_students=include_students,
    )
    _decorate_cohort(cohort)
    benchmark('end')
    return tolerant_jsonify(cohort)
Пример #25
0
def create_note():
    params = request.form
    sid = params.get('sid', None)
    subject = params.get('subject', None)
    body = params.get('body', None)
    topics = get_note_topics_from_http_post()
    if not sid or not subject:
        raise BadRequestError('Note creation requires \'subject\' and \'sid\'')
    user_dept_codes = dept_codes_where_advising(current_user)
    if current_user.is_admin or not len(user_dept_codes):
        raise ForbiddenRequestError(
            'Sorry, only advisors can create advising notes.')

    author_profile = _get_author_profile()
    attachments = get_note_attachments_from_http_post(tolerate_none=True)

    note = Note.create(
        **author_profile,
        subject=subject,
        body=process_input_from_rich_text_editor(body),
        topics=topics,
        sid=sid,
        attachments=attachments,
        template_attachment_ids=get_template_attachment_ids_from_http_post(),
    )
    note_read = NoteRead.find_or_create(current_user.get_id(), note.id)
    return tolerant_jsonify(
        _boa_note_to_compatible_json(note=note, note_read=note_read))
Пример #26
0
def delete_note(note_id):
    if not current_user.is_admin:
        raise ForbiddenRequestError('Sorry, you are not authorized to delete notes.')
    note = Note.find_by_id(note_id=note_id)
    if not note:
        raise ResourceNotFoundError('Note not found')
    Note.delete(note_id=note_id)
    return tolerant_jsonify({'message': f'Note {note_id} deleted'}), 200
Пример #27
0
def delete_note_template(note_template_id):
    note_template = NoteTemplate.find_by_id(note_template_id=note_template_id)
    if not note_template:
        raise ResourceNotFoundError('Template not found')
    if note_template.creator_id != current_user.get_id():
        raise ForbiddenRequestError('Template not available')
    NoteTemplate.delete(note_template_id=note_template_id)
    return tolerant_jsonify(
        {'message': f'Note template {note_template_id} deleted'}), 200
Пример #28
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))
Пример #29
0
def unreserve_appointment(appointment_id):
    appointment = Appointment.find_by_id(appointment_id)
    if not appointment:
        raise ResourceNotFoundError('Unknown path')
    has_privilege = current_user.is_admin or appointment.dept_code in _dept_codes_with_scheduler_privilege()
    if not has_privilege:
        raise ForbiddenRequestError(f'You are unauthorized to manage appointment {appointment_id}.')
    if appointment.status != 'reserved':
        raise BadRequestError(appointment.to_api_json(current_user.get_id()))
    _set_appointment_to_waiting(appointment)
    return Response(status=200)
Пример #30
0
def my_cohorts():
    domain = get_param(request.args, 'domain', 'default')
    if is_unauthorized_domain(domain):
        raise ForbiddenRequestError(
            f'You are unauthorized to query the \'{domain}\' domain')
    cohorts = []
    for cohort in CohortFilter.get_cohorts_of_user_id(current_user.get_id(),
                                                      domain=domain):
        cohort['isOwnedByCurrentUser'] = True
        cohorts.append(cohort)
    return tolerant_jsonify(cohorts)