Beispiel #1
0
def mock_note():
    user = AuthorizedUser.find_by_uid(coe_advisor_read_write_uid)
    template = DegreeProgressTemplate.create(
        advisor_dept_codes=['COENG'],
        created_by=user.id,
        degree_name='I am a mock template, made for a mock note',
    )
    return DegreeProgressNote.upsert(
        body='A mock note.',
        template_id=template.id,
        updated_by=user.id,
    )
Beispiel #2
0
def set_demo_mode():
    if app.config['DEMO_MODE_AVAILABLE']:
        in_demo_mode = request.get_json().get('demoMode', None)
        if in_demo_mode is None:
            raise errors.BadRequestError('Parameter \'demoMode\' not found')
        user = AuthorizedUser.find_by_id(current_user.get_id())
        user.in_demo_mode = bool(in_demo_mode)
        current_user.flush_cached()
        app.login_manager.reload_user()
        return tolerant_jsonify(current_user.to_api_json())
    else:
        raise errors.ResourceNotFoundError('Unknown path')
 def test_reserve_appointment(self, app, client, fake_auth):
     """Drop-in advisor can reserve an appointment."""
     dept_code = 'QCADV'
     advisor = DropInAdvisor.advisors_for_dept_code(dept_code)[0]
     user = AuthorizedUser.find_by_id(advisor.authorized_user_id)
     fake_auth.login(user.uid)
     waiting = AppointmentTestUtil.create_appointment(client, dept_code)
     appointment = self._reserve_appointment(client, waiting['id'])
     assert appointment['status'] == 'reserved'
     assert appointment['statusDate'] is not None
     assert appointment['statusBy']['id'] == user.id
     Appointment.delete(appointment['id'])
Beispiel #4
0
 def test_not_authenticated(self, app, client):
     """Returns 401 if not authenticated."""
     assert _api_note_create(
         app=app,
         author_id=AuthorizedUser.get_id_per_uid(coe_advisor_uid),
         body=
         'This is the last night of the fair, And the grease in the hair',
         client=client,
         expected_status_code=401,
         sids=[coe_student['sid']],
         subject='Rusholme Ruffians',
     )
Beispiel #5
0
    def test_load_admin_user(self):
        """Returns authorization record to Flask-Login for recognized UID."""
        admin_uid = '2040'
        loaded_user = AuthorizedUser.find_by_uid(admin_uid)
        assert loaded_user.is_active
        assert loaded_user.get_id() == admin_uid
        assert loaded_user.is_admin
        assert len(loaded_user.cohort_filters) > 0

        owners = loaded_user.cohort_filters[0].owners
        assert len(owners) > 0
        assert loaded_user in owners
Beispiel #6
0
def _get_coe_profiles():
    users = list(
        filter(lambda _user: '******' in _get_dept_codes(_user),
               AuthorizedUser.get_all_active_users()))
    profiles = []
    for user in authorized_users_api_feed(users):
        uid = user['uid']
        first_name = user.get('firstName')
        last_name = user.get('lastName')
        name = f'{first_name} {last_name}' if first_name or last_name else f'UID: {uid}'
        profiles.append({'name': name, 'value': uid})
    return sorted(profiles, key=lambda p: p['name'])
Beispiel #7
0
def add_university_dept_membership():
    params = request.get_json() or {}
    dept = UniversityDept.find_by_dept_code(params.get('deptCode', None))
    user = AuthorizedUser.find_by_uid(params.get('uid', None))
    membership = UniversityDeptMember.create_or_update_membership(
        university_dept=dept,
        authorized_user=user,
        is_advisor=params.get('isAdvisor', False),
        is_director=params.get('isDirector', False),
        is_scheduler=params.get('isScheduler', False),
        automate_membership=params.get('automateMembership', True),
    )
    return tolerant_jsonify(membership.to_api_json())
Beispiel #8
0
 def test_updated_date_is_none_when_note_create(self, app, client, fake_auth):
     """Create a note and expect none updated_at."""
     fake_auth.login(coe_advisor_uid)
     note = _api_note_create(
         app,
         client,
         author_id=AuthorizedUser.get_id_per_uid(coe_advisor_uid),
         sids=[coe_student['sid']],
         subject='Creating is not updating',
         body=None,
     )
     assert note['createdAt'] is not None
     assert note['updatedAt'] is None
Beispiel #9
0
    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
Beispiel #10
0
 def test_user_without_advising_data_access(self, app, client, fake_auth):
     """Denies access to a user who cannot access notes and appointments."""
     fake_auth.login(coe_advisor_no_advising_data_uid)
     user = AuthorizedUser.find_by_uid(coe_advisor_no_advising_data_uid)
     _api_batch_note_create(
         app,
         client,
         author_id=user.id,
         subject='Verboten',
         body='Diese Aktion ist nicht zulässig.',
         sids=self.sids,
         expected_status_code=401,
     )
Beispiel #11
0
 def test_create_note_prefers_ldap_dept_affiliation(self, app, client,
                                                    fake_auth):
     fake_auth.login(l_s_major_advisor_uid)
     new_note = _api_note_create(
         app,
         client,
         author_id=AuthorizedUser.get_id_per_uid(l_s_major_advisor_uid),
         sid=coe_student['sid'],
         subject='A dreaded sunny day',
         body='Keats and Yeats are on your side',
     )
     assert new_note['author']['departments'][0][
         'name'] == 'Department of English'
Beispiel #12
0
 def test_get_note_template_by_id(self, app, client, fake_auth):
     """Returns note templates created by current user."""
     fake_auth.login(l_s_major_advisor_uid)
     creator_id = AuthorizedUser.get_id_per_uid(l_s_major_advisor_uid)
     names = ['Johnny', 'Tommy', 'Joey', 'Dee Dee']
     for i in range(0, 4):
         NoteTemplate.create(creator_id=creator_id,
                             title=f'{names[i]}',
                             subject=f'Subject {i}')
     api_json = self._api_my_note_templates(client=client)
     expected_order = [template['title'] for template in api_json]
     expected_order.sort()
     assert expected_order == [template['title'] for template in api_json]
Beispiel #13
0
 def test_unauthorized_private_note(self, app, client, fake_auth):
     """Non-CE3 advisor cannot create a private note."""
     fake_auth.login(coe_advisor_uid)
     _api_note_create(
         app=app,
         author_id=AuthorizedUser.get_id_per_uid(coe_advisor_uid),
         body='She drove a Plymouth Satellite',
         client=client,
         expected_status_code=403,
         is_private=True,
         sids=[coe_student['sid']],
         subject='Planet Claire',
     )
Beispiel #14
0
 def test_admin_user_is_not_authorized(self, app, client, fake_auth):
     """Returns 401 if user is an admin."""
     fake_auth.login(admin_uid)
     admin = AuthorizedUser.find_by_uid(admin_uid)
     assert _api_note_create(
         app,
         client,
         author_id=admin.id,
         sids=[coe_student['sid']],
         subject='Rusholme Ruffians',
         body='This is the last night of the fair, And the grease in the hair',
         expected_status_code=403,
     )
Beispiel #15
0
 def test_scheduler_is_not_authorized(self, app, client, fake_auth):
     """Returns 401 if user is a scheduler."""
     fake_auth.login(coe_scheduler_uid)
     admin = AuthorizedUser.find_by_uid(coe_scheduler_uid)
     assert _api_note_create(
         app,
         client,
         author_id=admin.id,
         sids=[coe_student['sid']],
         subject='Gobbledygook',
         body='Language made unintelligible by excessive use of abstruse technical terms.',
         expected_status_code=401,
     )
Beispiel #16
0
def refresh_department_memberships():
    from boac.models.authorized_user import AuthorizedUser
    from boac.models.authorized_user_extension import DropInAdvisor, SameDayAdvisor, Scheduler
    from boac.models.university_dept import UniversityDept
    from boac.models.university_dept_member import UniversityDeptMember
    depts = UniversityDept.query.all()
    for dept in depts:
        dept.delete_automated_members()
    std_commit(allow_test_environment=True)
    for dept in depts:
        for membership in dept.memberships_from_loch():
            # A non-numeric "uid" indicates a row from SIS advising tables best ignored.
            uid = membership['uid']
            if not re.match(r'^\d+$', uid):
                continue
            user = AuthorizedUser.find_by_uid(uid, ignore_deleted=False)
            if user and not user.automate_degree_progress_permission:
                degree_progress_permission = user.degree_progress_permission
            else:
                degree_progress_permission = membership[
                    'degree_progress_permission']
            user = AuthorizedUser.create_or_restore(
                can_access_advising_data=membership[
                    'can_access_advising_data'],
                can_access_canvas_data=membership['can_access_canvas_data'],
                created_by='0',
                degree_progress_permission=degree_progress_permission,
                uid=uid,
            )
            if user:
                UniversityDeptMember.create_or_update_membership(
                    university_dept_id=dept.id,
                    authorized_user_id=user.id,
                    role='advisor',
                )
    DropInAdvisor.delete_orphans()
    SameDayAdvisor.delete_orphans()
    Scheduler.delete_orphans()
Beispiel #17
0
def get_coe_profiles():
    users = list(
        filter(lambda _user: '******' in _get_dept_codes(_user),
               AuthorizedUser.get_all_active_users()))
    calnet_users = get_calnet_users_for_uids(app, [u.uid for u in users])
    profiles = []
    for user in users:
        uid = user.uid
        calnet_user = calnet_users[uid]
        first_name = calnet_user.get('firstName')
        last_name = calnet_user.get('lastName')
        name = f'{first_name} {last_name}' if first_name or last_name else f'UID: {uid}'
        profiles.append({'name': name, 'value': uid})
    return sorted(profiles, key=lambda p: p['name'])
Beispiel #18
0
 def test_update_university_dept_membership(self, client, fake_auth):
     """Updates a UniversityDeptMember record."""
     fake_auth.login(admin_uid)
     self._api_add(client)
     membership = self._api_update(client,
                                   is_advisor=False,
                                   is_director=True)
     assert membership[
         'universityDeptId'] == UniversityDept.find_by_dept_code('ZZZZZ').id
     assert membership['authorizedUserId'] == AuthorizedUser.find_by_uid(
         coe_advisor_uid).id
     assert membership['isAdvisor'] is False
     assert membership['isDirector'] is True
     assert membership['automateMembership'] is False
 def test_curated_cohort_includes_alert_count(self, asc_advisor, client,
                                              create_alerts):
     """Successfully fetches curated_cohort with alert count per student."""
     user_id = AuthorizedUser.find_by_uid(asc_advisor_uid).id
     cohorts = CuratedCohort.get_curated_cohorts_by_owner_id(user_id)
     response = client.get(f'/api/curated_cohort/{cohorts[0].id}')
     students = response.json.get('students')
     assert students
     for student in students:
         assert isinstance(student.get('alertCount'), int)
     student_with_alerts = next(
         (s for s in students if s['sid'] == '11667051'), None)
     assert student_with_alerts
     assert student_with_alerts['alertCount'] == 3
Beispiel #20
0
 def test_update_note_template_topics(self, app, client, fake_auth,
                                      mock_note_template):
     """Update note template title."""
     user = AuthorizedUser.find_by_id(mock_note_template.creator_id)
     fake_auth.login(user.uid)
     expected_title = 'As cool as Kim Deal'
     api_json = self._api_note_template_rename(
         client,
         note_template_id=mock_note_template.id,
         title=expected_title,
     )
     assert api_json['title'] == expected_title
     assert NoteTemplate.find_by_id(
         mock_note_template.id).title == expected_title
Beispiel #21
0
 def test_create_private_note(self, app, client, fake_auth):
     """CE3 advisor can create a private note."""
     fake_auth.login(ce3_advisor_uid)
     note = _api_note_create(
         app=app,
         author_id=AuthorizedUser.get_id_per_uid(ce3_advisor_uid),
         body='Somebody went under a dock and there they saw a rock.',
         client=client,
         is_private=True,
         sids=[coe_student['sid']],
         subject='Rock Lobster',
     )
     assert note['isPrivate'] is True
     assert 'rock' in note['body']
Beispiel #22
0
 def test_get_note_by_id(self, app, client, fake_auth, new_coe_note):
     """Returns note in JSON compatible with BOA front-end."""
     fake_auth.login(coe_advisor_uid)
     note = self._api_note_by_id(client=client, note_id=new_coe_note.id)
     assert note
     assert 'id' in note
     assert note['type'] == 'note'
     assert note['body'] == note['message']
     assert note['read'] is False
     # Mark as read and re-test
     NoteRead.find_or_create(AuthorizedUser.get_id_per_uid(coe_advisor_uid),
                             note['id'])
     assert self._api_note_by_id(client=client,
                                 note_id=new_coe_note.id)['read'] is True
Beispiel #23
0
 def test_get_topic_usage_statistics(self, client, fake_auth):
     """Admin user can update a topic."""
     fake_auth.login(admin_uid)
     api_json = self._api_usage_statistics(client)
     assert list(api_json.keys()) == ['appointments', 'notes']
     assert len(api_json['appointments'])
     # Verify counts
     admin_user_id = AuthorizedUser.get_id_per_uid(uid=admin_uid)
     all_appointments = Appointment.query.filter(Appointment.deleted_at == None).all()  # noqa: E711
     all_appointments = [a.to_api_json(current_user_id=admin_user_id) for a in all_appointments]
     for topic_id, count in api_json['appointments'].items():
         topic = Topic.find_by_id(topic_id)
         matches = list(filter(lambda a: topic.topic in a['topics'], all_appointments))
         assert len(matches) == count
def remove_appointment_scheduler_from_dept(dept_code):
    _verify_membership_and_appointments_enabled(current_user, dept_code)
    params = request.get_json() or {}
    uid = params.get('uid')
    user = uid and AuthorizedUser.find_by_uid(uid)
    if not user:
        raise errors.BadRequestError(f'UID {uid} missing or invalid')
    scheduler_membership = next((
        d for d in user.department_memberships
        if d.university_dept.dept_code == dept_code and d.role == 'scheduler'),
                                None)
    if not scheduler_membership:
        raise errors.BadRequestError(
            f'UID {uid} is not a scheduler for department {dept_code}')
    UniversityDeptMember.delete_membership(
        university_dept_id=scheduler_membership.university_dept_id,
        authorized_user_id=user.id,
    )
    Scheduler.delete(authorized_user_id=user.id, dept_code=dept_code)
    if not len(user.department_memberships):
        AuthorizedUser.delete(uid)
    return tolerant_jsonify(
        _get_appointment_scheduler_list(current_user, dept_code))
 def test_feature_flag(self, client, fake_auth, app):
     """Appointments feature is false."""
     dept_code = 'QCADV'
     advisor = DropInAdvisor.advisors_for_dept_code(dept_code)[0]
     fake_auth.login(
         AuthorizedUser.find_by_id(advisor.authorized_user_id).uid)
     appointment = AppointmentTestUtil.create_appointment(client, dept_code)
     with override_config(app, 'FEATURE_FLAG_ADVISOR_APPOINTMENTS', False):
         self._cancel_appointment(
             client,
             appointment_id=appointment['id'],
             cancel_reason='Canceled by the power of the mind',
             expected_status_code=401,
         )
    def test_steal_appointment_reservation(self, app, client, fake_auth):
        """Reserve an appointment that another advisor has reserved."""
        dept_code = 'COENG'
        advisor_1 = DropInAdvisor.advisors_for_dept_code(dept_code)[0]
        user_1 = AuthorizedUser.find_by_id(advisor_1.authorized_user_id)
        fake_auth.login(user_1.uid)
        waiting = AppointmentTestUtil.create_appointment(client, dept_code)
        appointment = self._reserve_appointment(client, waiting['id'])
        assert appointment['status'] == 'reserved'
        assert appointment['statusDate'] is not None
        assert appointment['statusBy']['id'] == user_1.id
        client.get('/api/auth/logout')

        # Another advisor comes along...
        advisor_2 = DropInAdvisor.advisors_for_dept_code(dept_code)[1]
        user_2 = AuthorizedUser.find_by_id(advisor_2.authorized_user_id)
        fake_auth.login(user_2.uid)
        appointment = self._reserve_appointment(client, waiting['id'])
        assert appointment['status'] == 'reserved'
        assert appointment['statusDate'] is not None
        assert appointment['statusBy']['id'] == user_2.id
        # Clean up
        Appointment.delete(appointment['id'])
Beispiel #27
0
 def test_create_or_restore_new(self):
     """Creates a new user if it doesn't already exist."""
     new_user = AuthorizedUser.create_or_restore(
         unknown_uid,
         created_by='0',
         is_admin=False,
         can_access_advising_data=True,
         can_access_canvas_data=False,
     )
     assert new_user.is_admin is False
     assert new_user.can_access_advising_data is True
     assert new_user.can_access_canvas_data is False
     assert new_user.in_demo_mode is False
     assert new_user.created_by == '0'
Beispiel #28
0
def _create_waiting_appointments():
    coe_advisor_user_id = AuthorizedUser.get_id_per_uid('90412')
    coe_scheduler_user_id = AuthorizedUser.get_id_per_uid('6972201')
    l_s_director_user_id = AuthorizedUser.get_id_per_uid('53791')
    Appointment.create(
        appointment_type='Drop-in',
        created_by=coe_scheduler_user_id,
        dept_code='COENG',
        details='Meet me at the crossroads.',
        student_sid='3456789012',
        topics=['Topic for appointments, 2'],
    )
    Appointment.create(
        appointment_type='Drop-in',
        created_by=coe_advisor_user_id,
        dept_code='COENG',
        details='Life is what happens while you\'re making appointments.',
        student_sid='5678901234',
        topics=['Good Show'],
    )
    # L&S College Advising
    Appointment.create(
        appointment_type='Drop-in',
        created_by=l_s_director_user_id,
        dept_code='QCADV',
        details='C-c-catch the wave!',
        student_sid='5678901234',
        topics=['Topic for appointments, 1', 'Good Show'],
    )
    Appointment.create(
        appointment_type='Drop-in',
        created_by=l_s_director_user_id,
        dept_code='QCADV',
        details='You be you.',
        student_sid='11667051',
        topics=['Topic for appointments, 1'],
    )
Beispiel #29
0
    def test_respects_automate_memberships_flag(self, app, db):
        dept_coe = UniversityDept.query.filter_by(dept_code='COENG').first()
        manually_added_user = AuthorizedUser.create_or_restore(
            uid='1024',
            created_by='2040',
            degree_progress_permission='read_write',
        )
        manual_membership = UniversityDeptMember.create_or_update_membership(
            dept_coe.id,
            manually_added_user.id,
            role='advisor',
            automate_membership=False,
        )

        from boac.api.cache_utils import refresh_department_memberships
        refresh_department_memberships()
        std_commit(allow_test_environment=True)

        coe_users = [au.authorized_user for au in dept_coe.authorized_users]
        coe_user_count = len(coe_users)
        assert coe_user_count
        assert next(u for u in coe_users if u.uid == '1024')
        user = AuthorizedUser.find_by_uid(uid='1024')
        assert user
        assert user.degree_progress_permission == 'read_write'

        manual_membership.automate_membership = True
        db.session.add(manual_membership)
        std_commit(allow_test_environment=True)

        refresh_department_memberships()
        std_commit(allow_test_environment=True)

        coe_users = [au.authorized_user for au in dept_coe.authorized_users]
        assert len(coe_users) == coe_user_count - 1
        assert next((u for u in coe_users if u.uid == '1024'), None) is None
        assert not AuthorizedUser.find_by_uid(uid='1024')
Beispiel #30
0
 def test_create_note_with_raw_url_in_body(self, app, client, fake_auth):
     """Create a note with topics."""
     fake_auth.login(coe_advisor_uid)
     note = _api_note_create(
         app,
         client,
         author_id=AuthorizedUser.get_id_per_uid(coe_advisor_uid),
         sids=[coe_student['sid']],
         subject='Get rich quick',
         body='Get an online degree at send.money.edu university',
     )
     expected_body = 'Get an online degree at <a href="http://send.money.edu" target="_blank">send.money.edu</a> university'
     assert note.get('body') == expected_body
     assert note['createdAt'] is not None
     assert note['updatedAt'] is None