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())
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))
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)
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')
def _can_current_user_view_cohort(cohort): if current_user.is_admin or not cohort.get('owner'): return True cohort_dept_codes = cohort['owner'].get('deptCodes', []) if len(cohort_dept_codes): user_dept_codes = dept_codes_where_advising(current_user) return len([c for c in user_dept_codes if c in cohort_dept_codes]) else: return False
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
def create_degree(): params = request.get_json() name = get_param(params, 'name', None) validate_template_upsert(name=name) degree = DegreeProgressTemplate.create( advisor_dept_codes=dept_codes_where_advising(current_user), created_by=current_user.get_id(), degree_name=name, ) return tolerant_jsonify(degree.to_api_json())
def is_unauthorized_search(filter_keys, order_by=None): filter_key_set = set(filter_keys) asc_keys = {'inIntensiveCohort', 'isInactiveAsc', 'groupCodes'} if list(filter_key_set & asc_keys) or order_by in ['group_name']: if not current_user.is_admin and 'UWASC' not in dept_codes_where_advising(current_user): return True coe_keys = { 'coeAdvisorLdapUids', 'coeEthnicities', 'coeGenders', 'coePrepStatuses', 'coeProbation', 'coeUnderrepresented', 'isInactiveCoe', } if list(filter_key_set & coe_keys): if not current_user.is_admin and 'COENG' not in dept_codes_where_advising(current_user): return True return False
def _can_current_user_view_cohort(cohort): if current_user.is_admin or not cohort['owners']: return True cohort_dept_codes = { dept_code for o in cohort['owners'] for dept_code in o['deptCodes'] } if len(cohort_dept_codes): user_dept_codes = dept_codes_where_advising(current_user) return len([c for c in user_dept_codes if c in cohort_dept_codes]) else: return False
def clone(template, created_by, name=None, sid=None): clone = DegreeProgressTemplate.create( advisor_dept_codes=dept_codes_where_advising(current_user), created_by=created_by, degree_name=name or template.degree_name, parent_template_id=template.id if sid else None, student_sid=sid, ) unit_requirements_by_source_id = {} for unit_requirement in template.unit_requirements: source_id = unit_requirement.id unit_requirements_by_source_id[ source_id] = DegreeProgressUnitRequirement.create( created_by=created_by, min_units=unit_requirement.min_units, name=unit_requirement.name, template_id=clone.id, ) def _create_category(category_, parent_id): unit_requirement_ids = [] for u in category_['unitRequirements']: source_id_ = u['id'] cross_reference = unit_requirements_by_source_id[source_id_] unit_requirement_ids.append(cross_reference.id) return DegreeProgressCategory.create( category_type=category_['categoryType'], name=category_['name'], position=category_['position'], template_id=clone.id, course_units_lower=category_['unitsLower'], course_units_upper=category_['unitsUpper'], description=category_['description'], parent_category_id=parent_id, unit_requirement_ids=unit_requirement_ids, ) for category in DegreeProgressCategory.get_categories( template_id=template.id): c = _create_category(category_=category, parent_id=None) for course in category['courseRequirements']: _create_category(category_=course, parent_id=c.id) for subcategory in category['subcategories']: s = _create_category(category_=subcategory, parent_id=c.id) for course in subcategory['courseRequirements']: _create_category(category_=course, parent_id=s.id) # TODO: Unit requirements? return DegreeProgressTemplate.find_by_id(clone.id)
def _can_current_user_view_curated_group(curated_group): if current_user.is_admin: return True owner = AuthorizedUser.find_by_id(curated_group.owner_id) if not owner: return False curated_group_dept_codes = [ m.university_dept.dept_code for m in owner.department_memberships ] if len(curated_group_dept_codes): user_dept_codes = dept_codes_where_advising(current_user) return len( [c for c in user_dept_codes if c in curated_group_dept_codes]) else: return False
def get_student_query_scope(user=None): if user is None: user = current_user # Use department membership and admin status to determine what data we can surface about which students. # If this code is being called outside an HTTP request context, then assume it is an administrative task. # Not all current_user proxy types define all attributes, and so the ordering of these conditional checks # is important. if not user: return ['ADMIN'] elif hasattr(user, 'is_authenticated') and not user.is_authenticated: # This function can be invoked with both (1) user session object or (2) user record from the db. # User session object is identified by the presence of 'is_authenticated' method. return [] elif user.is_admin: return ['ADMIN'] elif hasattr(user, 'departments'): return dept_codes_where_advising(user) else: return [m.university_dept.dept_code for m in user.department_memberships]
def _get_author_profile(): author = current_user.to_api_json() calnet_profile = get_calnet_user_for_uid(app, author['uid']) if calnet_profile and calnet_profile.get('departments'): dept_codes = [dept.get('code') for dept in calnet_profile.get('departments')] else: dept_codes = dept_codes_where_advising(current_user) if calnet_profile and calnet_profile.get('title'): role = calnet_profile['title'] elif current_user.departments: role = current_user.departments[0]['role'] else: role = None return { 'author_uid': author['uid'], 'author_name': author['name'], 'author_role': role, 'author_dept_codes': dept_codes, }
def is_unauthorized_domain(domain): if domain not in ['default', 'admitted_students']: raise BadRequestError(f'Invalid domain: {domain}') elif domain == 'admitted_students' and not app.config[ 'FEATURE_FLAG_ADMITTED_STUDENTS']: raise ResourceNotFoundError('Unknown path') return domain == 'admitted_students' and not current_user.is_admin and 'ZCEEE' not in dept_codes_where_advising( current_user)