def get_valid_student_with_email(identifier): """ Helper function to get an user email from an identifier and validate it. In the UI a Coach can enroll users using both an email and an username. This function takes care of: - in case the identifier is an username, extracting the user object from the DB and then the associated email - validating the email Arguments: identifier (str): Username or email of the user to enroll Returns: (tuple): tuple containing: email (str): A validated email for the user to enroll. user (User): A valid User object or None. Raises: CCXUserValidationException: if the username is not found or the email is not valid. """ user = email = None try: user = get_student_from_identifier(identifier) except User.DoesNotExist: email = identifier else: email = user.email try: validate_email(email) except ValidationError: raise CCXUserValidationException( f'Could not find a user with name or email "{identifier}" ') # lint-amnesty, pylint: disable=raise-missing-from return email, user
def get_valid_student_with_email(identifier): """ Helper function to get an user email from an identifier and validate it. In the UI a Coach can enroll users using both an email and an username. This function takes care of: - in case the identifier is an username, extracting the user object from the DB and then the associated email - validating the email Arguments: identifier (str): Username or email of the user to enroll Returns: (tuple): tuple containing: email (str): A validated email for the user to enroll. user (User): A valid User object or None. Raises: CCXUserValidationException: if the username is not found or the email is not valid. """ user = email = None try: user = get_student_from_identifier(identifier) except User.DoesNotExist: email = identifier else: email = user.email try: validate_email(email) except ValidationError: raise CCXUserValidationException('Could not find a user with name or email "{0}" '.format(identifier)) return email, user
def add_member(request, slug): """ IN THE PROCESS OF BEING DEPRICATED! Create a new affiliate membership. """ member_identifier = request.POST.get('member_identifier') role = request.POST.get('role') affiliate = AffiliateEntity.objects.get(slug=slug) if role == AffiliateMembership.STAFF and not request.user.is_staff: messages.add_message(request, messages.INFO, 'You are not allowed to do that.') return redirect('affiliates:edit', slug=slug) try: member = get_student_from_identifier(member_identifier) except ObjectDoesNotExist: # create a user invite if the user does not exist invite_new_user(affiliate, member_identifier, role, request.user) messages.add_message( request, messages.INFO, 'User "{}" does not exist. They will be invited.'.format( member_identifier)) return redirect('affiliates:edit', slug=slug) params = { 'affiliate': affiliate, 'member': member, 'role': role, } AffiliateMembership.objects.create(**params) return redirect('affiliates:edit', slug=slug)
def create_new_affiliate(self, request): """ Creates a new AffiliateEntity instance based on data in the request. """ affiliate_request_data = self.get_affiliate_attributes_data( request.POST) affiliate = AffiliateEntity(**affiliate_request_data) # Only global staff users can set parent-child relationships if request.user.is_staff: parent_id = int(request.POST.get('parent', 0)) if parent_id: affiliate.parent = AffiliateEntity.objects.get(id=parent_id) else: affiliate.parent = None affiliate.save() affiliate_type = request.POST.get('affiliate-type') if request.user.is_staff and affiliate_type == 'parent': subs = dict(request.POST)['sub-affiliates'] AffiliateEntity.objects.filter(id__in=subs).update( parent=affiliate) # Affiliates app sends the PD ID (email). # If the attribute is sent (e.g. request comes from the affiliate app), # automatically create the PD membership for the passed in user. program_director_id = request.POST.get('member_identifier') if program_director_id: member = get_student_from_identifier(program_director_id) AffiliateMembership.objects.create(affiliate=affiliate, member=member, role=AffiliateMembership.STAFF) return affiliate
def create(request): """ IN THE PROCESS OF BEING DEPRICATED! Create a new affiliate. """ affiliate = AffiliateEntity() post_data = request.POST.copy().dict() program_director_identifier = post_data.pop('member_identifier', None) # delete image from POST since we pull it from FILES post_data.pop('image', None) if request.FILES and request.FILES['image']: setattr(affiliate, 'image', request.FILES['image']) for key in post_data: if key == 'program-director': continue if key == 'year_of_birth': setattr(affiliate, key, int(post_data[key])) elif key == 'parent': if not int(post_data[key]): continue parent = AffiliateEntity.objects.get(id=post_data[key]) setattr(affiliate, key, parent) else: setattr(affiliate, key, post_data[key]) affiliate.save() program_director_email = post_data.get('program-director') if program_director_email: try: program_director = User.objects.get(email=program_director_email) membership = AffiliateMembership.objects.create( member=program_director, role=AffiliateMembership.STAFF, affiliate=affiliate) LOG.info( 'Created new Program Director membership [%s] for affiliate [%s]', membership.id, affiliate.slug) except User.DoesNotExist: invite_new_user(affiliate, program_director_email, AffiliateMembership.STAFF, request.user) if request.user.is_staff and post_data.get('affiliate-type') == 'parent': subs = dict(request.POST)['sub-affiliates'] AffiliateEntity.objects.filter(id__in=subs).update(parent=affiliate) # SurveyGizmo functionality to automatically add Program Director upon creation if program_director_identifier: member = get_student_from_identifier(program_director_identifier) AffiliateMembership.objects.create(affiliate=affiliate, member=member, role='staff') return redirect('affiliates:affiliate-admin', affiliate_slug=affiliate.slug)
def delete_student_attempt(self, student_identifier, course_id, content_id, requesting_user): """ Deletes student state for a problem. requesting_user may be kept as an audit trail. Takes some of the following query parameters - student_identifier is an email or username - content_id is a url-name of a problem - course_id is the id for the course """ course_id = CourseKey.from_string(course_id) try: student = get_student_from_identifier(student_identifier) except ObjectDoesNotExist: err_msg = ( 'Error occurred while attempting to reset student attempts for user ' '{student_identifier} for content_id {content_id}. ' 'User does not exist!'.format( student_identifier=student_identifier, content_id=content_id ) ) log.error(err_msg) return try: module_state_key = UsageKey.from_string(content_id) except InvalidKeyError: err_msg = ( 'Invalid content_id {content_id}!'.format(content_id=content_id) ) log.error(err_msg) return if student: try: enrollment.reset_student_attempts( course_id, student, module_state_key, requesting_user=requesting_user, delete_module=True, ) except (StudentModule.DoesNotExist, enrollment.sub_api.SubmissionError): err_msg = ( 'Error occurred while attempting to reset student attempts for user ' '{student_identifier} for content_id {content_id}.'.format( student_identifier=student_identifier, content_id=content_id ) ) log.error(err_msg)
def delete_student_attempt(self, student_identifier, course_id, content_id, requesting_user): """ Deletes student state for a problem. requesting_user may be kept as an audit trail. Takes some of the following query parameters - student_identifier is an email or username - content_id is a url-name of a problem - course_id is the id for the course """ course_id = CourseKey.from_string(course_id) try: student = get_student_from_identifier(student_identifier) except ObjectDoesNotExist: err_msg = ( 'Error occurred while attempting to reset student attempts for user ' '{student_identifier} for content_id {content_id}. ' 'User does not exist!'.format( student_identifier=student_identifier, content_id=content_id ) ) log.error(err_msg) return try: module_state_key = UsageKey.from_string(content_id) except InvalidKeyError: err_msg = ( f'Invalid content_id {content_id}!' ) log.error(err_msg) return if student: try: enrollment.reset_student_attempts( course_id, student, module_state_key, requesting_user=requesting_user, delete_module=True, ) except (StudentModule.DoesNotExist, enrollment.sub_api.SubmissionError): err_msg = ( 'Error occurred while attempting to reset student attempts for user ' '{student_identifier} for content_id {content_id}.'.format( student_identifier=student_identifier, content_id=content_id ) ) log.error(err_msg)
def post(self, request, *args, **kwargs): course_id = request.POST.get('course_id', False) try: course_id = SlashSeparatedCourseKey.from_deprecated_string( course_id) except Exception: course_id = None if not course_id: self.msg = u"课程ID错误" context = {'msg': self.msg, 'datatable': self.make_datatable()} return render_to_response(self.template_name, context) elif not request.POST.get('identifiers'): self.msg = u"邮箱用户名错误" context = {'msg': self.msg, 'datatable': self.make_datatable()} return render_to_response(self.template_name, context) action = request.POST.get('action') identifiers_raw = request.POST.get('identifiers') identifiers = _split_input_list(identifiers_raw) auto_enroll = _get_boolean_param(request, 'auto_enroll') email_students = _get_boolean_param(request, 'email_students') is_white_label = CourseMode.is_white_label(course_id) reason = request.POST.get('reason') if is_white_label: if not reason: self.msg = "400" context = {'msg': self.msg, 'datatable': self.make_datatable()} return render_to_response(self.template_name, context) enrollment_obj = None state_transition = DEFAULT_TRANSITION_STATE email_params = {} if email_students: course = get_course_by_id(course_id) email_params = get_email_params(course, auto_enroll, secure=request.is_secure()) results = [] for identifier in identifiers: # First try to get a user object from the identifer user = None email = None language = None try: user = get_student_from_identifier(identifier) except User.DoesNotExist: email = identifier else: email = user.email language = get_user_email_language(user) try: # Use django.core.validators.validate_email to check email address # validity (obviously, cannot check if email actually /exists/, # simply that it is plausibly valid) validate_email(email) # Raises ValidationError if invalid if action == 'enroll': before, after, enrollment_obj = enroll_email( course_id, email, auto_enroll, email_students, email_params, language=language) before_enrollment = before.to_dict()['enrollment'] before_user_registered = before.to_dict()['user'] before_allowed = before.to_dict()['allowed'] after_enrollment = after.to_dict()['enrollment'] after_allowed = after.to_dict()['allowed'] if before_user_registered: if after_enrollment: if before_enrollment: state_transition = ENROLLED_TO_ENROLLED else: if before_allowed: state_transition = ALLOWEDTOENROLL_TO_ENROLLED else: state_transition = UNENROLLED_TO_ENROLLED else: if after_allowed: state_transition = UNENROLLED_TO_ALLOWEDTOENROLL elif action == 'unenroll': before, after = unenroll_email(course_id, email, email_students, email_params, language=language) before_enrollment = before.to_dict()['enrollment'] before_allowed = before.to_dict()['allowed'] enrollment_obj = CourseEnrollment.get_enrollment( user, course_id) if before_enrollment: state_transition = ENROLLED_TO_UNENROLLED else: if before_allowed: state_transition = ALLOWEDTOENROLL_TO_UNENROLLED else: state_transition = UNENROLLED_TO_UNENROLLED else: return HttpResponseBadRequest( strip_tags("Unrecognized action '{}'".format(action))) except ValidationError: # Flag this email as an error if invalid, but continue checking # the remaining in the list results.append({ 'identifier': identifier, 'invalidIdentifier': True, }) except Exception as exc: # pylint: disable=broad-except # catch and log any exceptions # so that one error doesn't cause a 500. log.exception(u"Error while #{}ing student") log.exception(exc) results.append({ 'identifier': identifier, 'error': True, }) else: ManualEnrollmentAudit.create_manual_enrollment_audit( request.user, email, state_transition, reason, enrollment_obj) results.append({ 'identifier': identifier, 'before': before.to_dict(), 'after': after.to_dict(), }) invalid_id = [] valid_id = [] for result in results: if ('error' in result) or ('invalidIdentifier' in result): invalid_id.append(result['identifier']) else: valid_id.append(result['identifier']) invalid_message = [ "{} 无效 <br>".format(i.encode('utf-8')) for i in invalid_id ] valid_message = [] action = "选课" if action == "enroll" else "弃选" for i in valid_id: if action == "弃选": valid_message.append("{0} {1} 成功 <br>".format(i, action)) continue if email_students: valid_message.append("{0} {1} 成功,并向他发送电子邮件 <br>".format( i, action)) else: valid_message.append("{0} {1} 成功<br>".format(i, action)) invalid_message.extend(valid_message) self.msg = "".join(invalid_message) context = {'msg': self.msg, 'datatable': self.make_datatable()} return render_to_response(self.template_name, context)
def enroll_user_to_course(request_info, course_id, username_or_email): """ Look up the given user, and if successful, enroll them to the specified course. Arguments: request_info (dict): Dict containing task request information course_id (str): The ID string of the course username_or_email: user's username or email string Returns: User object (or None if user in not registered, and whether the user is already enrolled or not """ # First try to get a user object from the identifier (email) user = None user_already_enrolled = False language = None email_students = True auto_enroll = True thread_site = Site.objects.get(domain=request_info['host']) thread_author = User.objects.get(username=request_info['username']) try: user = get_student_from_identifier(username_or_email) except User.DoesNotExist: email = username_or_email else: email = user.email language = get_user_email_language(user) if user: course_enrollment = CourseEnrollment.get_enrollment( user=user, course_key=course_id) if course_enrollment: user_already_enrolled = True # Set the enrollment to active if its not already active if not course_enrollment.is_active: course_enrollment.update_enrollment(is_active=True) if not user or not user_already_enrolled: course = get_course_by_id(course_id, depth=0) try: with emulate_http_request(site=thread_site, user=thread_author): email_params = get_email_params(course, auto_enroll) __ = enroll_email(course_id, email, auto_enroll, email_students, email_params, language=language) if user: TASK_LOG.info( u'User %s enrolled successfully in course %s via CSV bulk enrollment', username_or_email, course_id) except: TASK_LOG.exception( u'There was an error enrolling user %s in course %s via CSV bulk enrollment', username_or_email, course_id) return None, None return user, user_already_enrolled