Esempio n. 1
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)
Esempio n. 2
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))
Esempio n. 3
0
def _update_drop_in_status(uid, dept_code, active):
    dept_code = dept_code.upper()
    if uid == 'me':
        uid = current_user.get_uid()
    else:
        authorized_to_toggle = current_user.is_admin or dept_code in [
            d['code'] for d in current_user.departments if d.get('isScheduler')
        ]
        if not authorized_to_toggle:
            raise errors.ForbiddenRequestError(
                f'Unauthorized to toggle drop-in status for department {dept_code}'
            )
    drop_in_status = None
    user = AuthorizedUser.find_by_uid(uid)
    if user:
        drop_in_status = next(
            (d for d in user.drop_in_departments if d.dept_code == dept_code),
            None)
    if drop_in_status:
        drop_in_status.update_availability(active)
        UserSession.flush_cache_for_id(user.id)
        return tolerant_jsonify(drop_in_status.to_api_json())
    else:
        raise errors.ResourceNotFoundError(
            f'No drop-in advisor status found: (uid={uid}, dept_code={dept_code})'
        )
Esempio n. 4
0
def add_appointment_scheduler_to_dept(dept_code):
    _verify_membership_and_appointments_enabled(current_user, dept_code)
    params = request.get_json() or {}
    scheduler_uid = params.get('uid', None)
    if not scheduler_uid:
        raise errors.BadRequestError('Scheduler UID missing')
    calnet_user = calnet.get_calnet_user_for_uid(app,
                                                 scheduler_uid,
                                                 skip_expired_users=True)
    if not calnet_user or not calnet_user.get('csid'):
        raise errors.BadRequestError('Invalid scheduler UID')
    user = AuthorizedUser.create_or_restore(
        scheduler_uid,
        created_by=current_user.get_uid(),
        is_admin=False,
        is_blocked=False,
        can_access_canvas_data=False,
    )
    Scheduler.create_or_update_membership(
        dept_code,
        user.id,
        drop_in=True,
        same_day=True,
    )
    _create_department_memberships(user, [{
        'code': dept_code,
        'role': 'scheduler',
        'automateMembership': False
    }])
    UserSession.flush_cache_for_id(user.id)
    return tolerant_jsonify(
        _get_appointment_scheduler_list(current_user, dept_code))
Esempio n. 5
0
def _update_drop_in_availability(uid, dept_code, new_availability):
    dept_code = dept_code.upper()
    if uid != current_user.get_uid():
        authorized_to_toggle = current_user.is_admin or dept_code in [
            d['code']
            for d in current_user.departments if d.get('role') == 'scheduler'
        ]
        if not authorized_to_toggle:
            raise errors.ForbiddenRequestError(
                f'Unauthorized to toggle drop-in availability for department {dept_code}'
            )
    drop_in_membership = None
    user = AuthorizedUser.find_by_uid(uid)
    if user:
        drop_in_membership = next(
            (d for d in user.drop_in_departments if d.dept_code == dept_code),
            None)
    if drop_in_membership:
        if drop_in_membership.is_available is True and new_availability is False:
            Appointment.unreserve_all_for_advisor(uid, current_user.get_id())
        drop_in_membership.update_availability(new_availability)
        UserSession.flush_cache_for_id(user.id)
        return tolerant_jsonify(drop_in_membership.to_api_json())
    else:
        raise errors.ResourceNotFoundError(
            f'No drop-in advisor membership found: (uid={uid}, dept_code={dept_code})'
        )
Esempio n. 6
0
def _get_filter_db_type_per_key(domain):
    filter_type_per_key = {}
    option_groups = CohortFilterOptions.get_cohort_filter_option_groups(
        current_user.get_uid(), domain)
    for label, option_group in option_groups.items():
        for option in option_group:
            filter_type_per_key[option['key']] = option['type']['db']
    return filter_type_per_key
Esempio n. 7
0
def _update_or_create_authorized_user(memberships,
                                      profile,
                                      include_deleted=False):
    user_id = profile.get('id')
    automate_degree_progress_permission = profile.get(
        'automateDegreeProgressPermission')
    can_access_canvas_data = to_bool_or_none(
        profile.get('canAccessCanvasData'))
    can_access_advising_data = to_bool_or_none(
        profile.get('canAccessAdvisingData'))
    degree_progress_permission = profile.get('degreeProgressPermission')

    if (automate_degree_progress_permission or degree_progress_permission
        ) and 'COENG' not in dept_codes_where_advising(
            {'departments': memberships}):
        raise errors.BadRequestError(
            'Degree Progress feature is only available to the College of Engineering.'
        )

    is_admin = to_bool_or_none(profile.get('isAdmin'))
    is_blocked = to_bool_or_none(profile.get('isBlocked'))
    if user_id:
        user = AuthorizedUser.update_user(
            automate_degree_progress_permission=
            automate_degree_progress_permission,
            can_access_advising_data=can_access_advising_data,
            can_access_canvas_data=can_access_canvas_data,
            degree_progress_permission=degree_progress_permission,
            include_deleted=include_deleted,
            is_admin=is_admin,
            is_blocked=is_blocked,
            user_id=user_id,
        )
        UserSession.flush_cache_for_id(user_id=user_id)
        return user
    else:
        uid = profile.get('uid')
        if AuthorizedUser.get_id_per_uid(uid, include_deleted=True):
            raise errors.BadRequestError(
                f'User with UID {uid} is already in the BOA database.')

        calnet_user = calnet.get_calnet_user_for_uid(app,
                                                     uid,
                                                     skip_expired_users=True)
        if calnet_user and calnet_user.get('csid', None):
            return AuthorizedUser.create_or_restore(
                automate_degree_progress_permission=
                automate_degree_progress_permission,
                can_access_advising_data=can_access_advising_data,
                can_access_canvas_data=can_access_canvas_data,
                created_by=current_user.get_uid(),
                degree_progress_permission=degree_progress_permission,
                is_admin=is_admin,
                is_blocked=is_blocked,
                uid=uid,
            )
        else:
            raise errors.BadRequestError('Invalid UID')
Esempio n. 8
0
def translate_cohort_filter_to_menu(cohort_owner_uid):
    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')
    if cohort_owner_uid == 'me':
        cohort_owner_uid = current_user.get_uid()
    criteria = get_param(params, 'criteria')
    return tolerant_jsonify(
        CohortFilterOptions.translate_to_filter_options(
            cohort_owner_uid, domain, criteria))
Esempio n. 9
0
def all_cohort_filter_options(cohort_owner_uid):
    if cohort_owner_uid == 'me':
        cohort_owner_uid = current_user.get_uid()
    params = request.get_json()
    existing_filters = get_param(params, 'existingFilters', [])
    domain = get_param(params, 'domain', 'default')
    if is_unauthorized_domain(domain):
        raise ForbiddenRequestError(
            f'You are unauthorized to query the \'{domain}\' domain')
    return tolerant_jsonify(
        CohortFilterOptions.get_cohort_filter_option_groups(
            cohort_owner_uid,
            domain,
            existing_filters,
        ), )
Esempio n. 10
0
def remove_attachment(note_id, attachment_id):
    existing_note = Note.find_by_id(note_id=note_id)
    if not existing_note:
        raise BadRequestError('Note id not found.')
    if existing_note.author_uid != current_user.get_uid() and not current_user.is_admin:
        raise ForbiddenRequestError('You are not authorized to remove attachments from this note.')
    note = Note.delete_attachment(
        note_id=note_id,
        attachment_id=int(attachment_id),
    )
    return tolerant_jsonify(
        _boa_note_to_compatible_json(
            note=note,
            note_read=NoteRead.find_or_create(current_user.get_id(), note_id),
        ),
    )
Esempio n. 11
0
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)
Esempio n. 12
0
def update_note():
    params = request.form
    note_id = params.get('id', None)
    subject = params.get('subject', None)
    body = params.get('body', None)
    topics = get_note_topics_from_http_post()
    if not note_id or not subject:
        raise BadRequestError('Note requires \'id\' and \'subject\'')
    if Note.find_by_id(note_id=note_id).author_uid != current_user.get_uid():
        raise ForbiddenRequestError('Sorry, you are not the author of this note.')
    note = Note.update(
        note_id=note_id,
        subject=subject,
        body=process_input_from_rich_text_editor(body),
        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))
Esempio n. 13
0
def add_attachment(note_id):
    if Note.find_by_id(note_id=note_id).author_uid != current_user.get_uid():
        raise ForbiddenRequestError('Sorry, you are not the author of this note.')
    attachments = _get_attachments(request.files)
    if len(attachments) != 1:
        raise BadRequestError('A single attachment file must be supplied.')
    note = Note.add_attachment(
        note_id=note_id,
        attachment=attachments[0],
    )
    note_json = note.to_api_json()
    return tolerant_jsonify(
        note_to_compatible_json(
            note=note_json,
            note_read=NoteRead.find_or_create(current_user.get_id(), note_id),
            attachments=note_json.get('attachments'),
            topics=note_json.get('topics'),
        ),
    )
Esempio n. 14
0
def add_attachments(note_id):
    note = Note.find_by_id(note_id=note_id)
    if note.author_uid != current_user.get_uid():
        raise ForbiddenRequestError('Sorry, you are not the author of this note.')
    attachments = get_note_attachments_from_http_post()
    attachment_limit = app.config['NOTES_ATTACHMENTS_MAX_PER_NOTE']
    if len(attachments) + len(note.attachments) > attachment_limit:
        raise BadRequestError(f'No more than {attachment_limit} attachments may be uploaded at once.')
    for attachment in attachments:
        note = Note.add_attachment(
            note_id=note_id,
            attachment=attachment,
        )
    return tolerant_jsonify(
        _boa_note_to_compatible_json(
            note=note,
            note_read=NoteRead.find_or_create(current_user.get_id(), note_id),
        ),
    )
Esempio n. 15
0
def update_note():
    params = request.form
    note_id = params.get('id', None)
    subject = params.get('subject', None)
    body = params.get('body', None)
    topics = _get_topics(params)
    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_]
    if not note_id or not subject:
        raise BadRequestError('Note requires \'id\' and \'subject\'')
    if Note.find_by_id(note_id=note_id).author_uid != current_user.get_uid():
        raise ForbiddenRequestError('Sorry, you are not the author of this note.')
    note = Note.update(
        note_id=note_id,
        subject=subject,
        body=process_input_from_rich_text_editor(body),
        topics=topics,
        attachments=_get_attachments(request.files, tolerate_none=True),
        delete_attachment_ids=delete_attachment_ids,
    )
    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))
Esempio n. 16
0
def _get_filter_db_type_per_key():
    filter_type_per_key = {}
    for category in get_cohort_filter_options(current_user.get_uid()):
        for _filter in category:
            filter_type_per_key[_filter['key']] = _filter['type']['db']
    return filter_type_per_key
Esempio n. 17
0
def _decorate_cohort(cohort):
    owner_uids = [o['uid'] for o in cohort['owners']]
    cohort.update(
        {'isOwnedByCurrentUser': current_user.get_uid() in owner_uids})
Esempio n. 18
0
def translate_cohort_filter_to_menu(cohort_owner_uid):
    if cohort_owner_uid == 'me':
        cohort_owner_uid = current_user.get_uid()
    criteria = get_param(request.get_json(), 'criteria')
    return tolerant_jsonify(
        translate_to_filter_options(cohort_owner_uid, criteria))
Esempio n. 19
0
def all_cohort_filter_options(cohort_owner_uid):
    if cohort_owner_uid == 'me':
        cohort_owner_uid = current_user.get_uid()
    existing_filters = get_param(request.get_json(), 'existingFilters', [])
    return tolerant_jsonify(
        get_cohort_filter_options(cohort_owner_uid, existing_filters))
Esempio n. 20
0
def _decorate_cohort(cohort):
    if cohort.get('owner'):
        cohort.update({
            'isOwnedByCurrentUser':
            cohort['owner'].get('uid') == current_user.get_uid()
        })