Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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)
Beispiel #4
0
    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
Beispiel #5
0
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)
Beispiel #8
0
    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)
Beispiel #9
0
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