コード例 #1
0
ファイル: views.py プロジェクト: andela-ijubril/edx-platform
def get_valid_student_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:
        str: A validated email for the user to enroll

    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
コード例 #2
0
ファイル: views.py プロジェクト: rhndg/openedx
def ccx_student_management(request, course):
    """Manage the enrollment of individual students in a CCX
    """
    ccx = get_ccx_for_coach(course, request.user)
    action = request.POST.get("student-action", None)
    student_id = request.POST.get("student-id", "")
    user = email = None
    try:
        user = get_student_from_identifier(student_id)
    except User.DoesNotExist:
        email = student_id
    else:
        email = user.email

    try:
        validate_email(email)
        if action == "add":
            # by decree, no emails sent to students added this way
            # by decree, any students added this way are auto_enrolled
            enroll_email(ccx, email, auto_enroll=True, email_students=False)
        elif action == "revoke":
            unenroll_email(ccx, email, email_students=False)
    except ValidationError:
        log.info("Invalid user name or email when trying to enroll student: %s", email)

    url = reverse("ccx_coach_dashboard", kwargs={"course_id": course.id})
    return redirect(url)
コード例 #3
0
def ccx_student_management(request, course, ccx=None):
    """Manage the enrollment of individual students in a CCX
    """
    if not ccx:
        raise Http404

    action = request.POST.get('student-action', None)
    student_id = request.POST.get('student-id', '')
    user = email = None
    try:
        user = get_student_from_identifier(student_id)
    except User.DoesNotExist:
        email = student_id
    else:
        email = user.email

    course_key = CCXLocator.from_course_locator(course.id, ccx.id)
    try:
        validate_email(email)
        if action == 'add':
            # by decree, no emails sent to students added this way
            # by decree, any students added this way are auto_enrolled
            enroll_email(course_key, email, auto_enroll=True, email_students=False)
        elif action == 'revoke':
            unenroll_email(course_key, email, email_students=False)
    except ValidationError:
        log.info('Invalid user name or email when trying to enroll student: %s', email)

    url = reverse(
        'ccx_coach_dashboard',
        kwargs={'course_id': course_key}
    )
    return redirect(url)
コード例 #4
0
ファイル: views.py プロジェクト: regisb/fun-apps
def modify_special_forum_contributors(request, course_id):

    unique_student_identifier = request.GET.get('unique_student_identifier')
    rolename = request.GET.get('rolename')
    action = request.GET.get('action')

    try:
        course_id = _check_rights(course_id, request.user, rolename)
    except UnauthorizedAccessError as e:
        return HttpResponseBadRequest(e.message)
    course = get_course_by_id(course_id)
    _check_custom_roles(course_id)

    user = get_student_from_identifier(unique_student_identifier)
    target_is_instructor = has_access(user, 'instructor', course)
    # cannot revoke instructor
    if target_is_instructor and action == 'revoke' and rolename == FORUM_ROLE_ADMINISTRATOR:
        return HttpResponseBadRequest("Cannot revoke instructor forum admin privileges.")
    try:
        update_forum_role(course_id, user, rolename, action)
    except Role.DoesNotExist:
        return HttpResponseBadRequest("Role does not exist.")

    response_payload = {
        'course_id': course_id.to_deprecated_string(),
        'action': action,
    }
    return JsonResponse(response_payload)
コード例 #5
0
ファイル: views.py プロジェクト: julAtWork/fun-apps
def modify_special_forum_contributors(request, course_id):

    unique_student_identifier = request.GET.get('unique_student_identifier')
    rolename = request.GET.get('rolename')
    action = request.GET.get('action')

    try:
        course_id = _check_rights(course_id, request.user, rolename)
    except UnauthorizedAccessError as e:
        return HttpResponseBadRequest(e.message)
    course = get_course_by_id(course_id)
    _check_custom_roles(course_id)

    user = get_student_from_identifier(unique_student_identifier)
    target_is_instructor = has_access(user, 'instructor', course)
    # cannot revoke instructor
    if target_is_instructor and action == 'revoke' and rolename == FORUM_ROLE_ADMINISTRATOR:
        return HttpResponseBadRequest("Cannot revoke instructor forum admin privileges.")
    try:
        update_forum_role(course_id, user, rolename, action)
    except Role.DoesNotExist:
        return HttpResponseBadRequest("Role does not exist.")

    response_payload = {
        'course_id': course_id.to_deprecated_string(),
        'action': action,
    }
    return JsonResponse(response_payload)
コード例 #6
0
def ccx_invite(request, course):
    """
    Invite users to new ccx
    """
    ccx = get_ccx_for_coach(course, request.user)
    action = request.POST.get('enrollment-button')
    identifiers_raw = request.POST.get('student-ids')
    identifiers = _split_input_list(identifiers_raw)
    auto_enroll = True if 'auto-enroll' in request.POST else False
    email_students = True if 'email-students' in request.POST else False
    for identifier in identifiers:
        user = None
        email = None
        try:
            user = get_student_from_identifier(identifier)
        except User.DoesNotExist:
            email = identifier
        else:
            email = user.email
        try:
            validate_email(email)
            if action == 'Enroll':
                enroll_email(ccx,
                             email,
                             auto_enroll=auto_enroll,
                             email_students=email_students)
            if action == "Unenroll":
                unenroll_email(ccx, email, email_students=email_students)
        except ValidationError:
            log.info(
                'Invalid user name or email when trying to invite students: %s',
                email)
    url = reverse('ccx_coach_dashboard', kwargs={'course_id': course.id})
    return redirect(url)
コード例 #7
0
ファイル: views.py プロジェクト: Cgruppo/edx-platform
def ccx_invite(request, course):
    """
    Invite users to new ccx
    """
    ccx = get_ccx_for_coach(course, request.user)
    action = request.POST.get('enrollment-button')
    identifiers_raw = request.POST.get('student-ids')
    identifiers = _split_input_list(identifiers_raw)
    auto_enroll = True if 'auto-enroll' in request.POST else False
    email_students = True if 'email-students' in request.POST else False
    for identifier in identifiers:
        user = None
        email = None
        try:
            user = get_student_from_identifier(identifier)
        except User.DoesNotExist:
            email = identifier
        else:
            email = user.email
        try:
            validate_email(email)
            if action == 'Enroll':
                enroll_email(
                    ccx,
                    email,
                    auto_enroll=auto_enroll,
                    email_students=email_students
                )
            if action == "Unenroll":
                unenroll_email(ccx, email, email_students=email_students)
        except ValidationError:
            log.info('Invalid user name or email when trying to invite students: %s', email)
    url = reverse('ccx_coach_dashboard', kwargs={'course_id': course.id})
    return redirect(url)
コード例 #8
0
ファイル: views.py プロジェクト: adoosii/edx-platform
def ccx_student_management(request, course, ccx=None):
    """Manage the enrollment of individual students in a CCX
    """
    if not ccx:
        raise Http404

    action = request.POST.get("student-action", None)
    student_id = request.POST.get("student-id", "")
    user = email = None
    error_message = ""
    course_key = CCXLocator.from_course_locator(course.id, ccx.id)
    try:
        user = get_student_from_identifier(student_id)
    except User.DoesNotExist:
        email = student_id
        error_message = validate_student_email(email)
        if email and not error_message:
            error_message = _('Could not find a user with name or email "{email}" ').format(email=email)
    else:
        email = user.email
        error_message = validate_student_email(email)

    if error_message is None:
        if action == "add":
            # by decree, no emails sent to students added this way
            # by decree, any students added this way are auto_enrolled
            enroll_email(course_key, email, auto_enroll=True, email_students=False)
        elif action == "revoke":
            unenroll_email(course_key, email, email_students=False)
    else:
        messages.error(request, error_message)

    url = reverse("ccx_coach_dashboard", kwargs={"course_id": course_key})
    return redirect(url)
コード例 #9
0
ファイル: views.py プロジェクト: adoosii/edx-platform
def ccx_invite(request, course, ccx=None):
    """
    Invite users to new ccx
    """
    if not ccx:
        raise Http404

    action = request.POST.get("enrollment-button")
    identifiers_raw = request.POST.get("student-ids")
    identifiers = _split_input_list(identifiers_raw)
    auto_enroll = True if "auto-enroll" in request.POST else False
    email_students = True if "email-students" in request.POST else False
    for identifier in identifiers:
        user = None
        email = None
        try:
            user = get_student_from_identifier(identifier)
        except User.DoesNotExist:
            email = identifier
        else:
            email = user.email
        try:
            validate_email(email)
            course_key = CCXLocator.from_course_locator(course.id, ccx.id)
            email_params = get_email_params(course, auto_enroll, course_key=course_key, display_name=ccx.display_name)
            if action == "Enroll":
                enroll_email(
                    course_key, email, auto_enroll=auto_enroll, email_students=email_students, email_params=email_params
                )
            if action == "Unenroll":
                unenroll_email(course_key, email, email_students=email_students, email_params=email_params)
        except ValidationError:
            log.info("Invalid user name or email when trying to invite students: %s", email)
    url = reverse("ccx_coach_dashboard", kwargs={"course_id": CCXLocator.from_course_locator(course.id, ccx.id)})
    return redirect(url)
コード例 #10
0
ファイル: utils.py プロジェクト: Endika/edx-platform
def get_valid_student_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:
        str: A validated email for the user to enroll

    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
コード例 #11
0
ファイル: services.py プロジェクト: 10clouds/edx-platform
    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)
コード例 #12
0
    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)
コード例 #13
0
def ccx_invite(request, course, ccx=None):
    """
    Invite users to new ccx
    """
    if not ccx:
        raise Http404

    action = request.POST.get('enrollment-button')
    identifiers_raw = request.POST.get('student-ids')
    identifiers = _split_input_list(identifiers_raw)
    auto_enroll = True if 'auto-enroll' in request.POST else False
    email_students = True if 'email-students' in request.POST else False
    for identifier in identifiers:
        user = None
        email = None
        try:
            user = get_student_from_identifier(identifier)
        except User.DoesNotExist:
            email = identifier
        else:
            email = user.email
        try:
            validate_email(email)
            course_key = CCXLocator.from_course_locator(course.id, ccx.id)
            email_params = get_email_params(course,
                                            auto_enroll,
                                            course_key=course_key,
                                            display_name=ccx.display_name)
            if action == 'Enroll':
                enroll_email(course_key,
                             email,
                             auto_enroll=auto_enroll,
                             email_students=email_students,
                             email_params=email_params)
            if action == "Unenroll":
                unenroll_email(course_key,
                               email,
                               email_students=email_students,
                               email_params=email_params)
        except ValidationError:
            log.info(
                'Invalid user name or email when trying to invite students: %s',
                email)
    url = reverse('ccx_coach_dashboard',
                  kwargs={
                      'course_id':
                      CCXLocator.from_course_locator(course.id, ccx.id)
                  })
    return redirect(url)
コード例 #14
0
def rescore_problem(request, course_id):
    """
    Starts a background process a students attempts counter. Optionally deletes student state for a problem.
    Limited to instructor access.

    Takes either of the following query paremeters
        - problem_to_reset is a urlname of a problem
        - unique_student_identifier is an email or username
        - all_students is a boolean

    all_students and unique_student_identifier cannot both be present.
    """
    problem_to_reset = strip_if_string(request.GET.get('problem_to_reset'))
    student_identifier = request.GET.get('unique_student_identifier', None)
    student = None
    if student_identifier is not None:
        student = get_student_from_identifier(student_identifier)

    all_students = request.GET.get('all_students') in ['true', 'True', True]

    if not (problem_to_reset and (all_students or student)):
        return HttpResponseBadRequest("Missing query parameters.")

    if all_students and student:
        return HttpResponseBadRequest(
            "Cannot rescore with all_students and unique_student_identifier.")

    module_state_key = _msk_from_problem_urlname(course_id, problem_to_reset)

    response_payload = {}
    response_payload['problem_to_reset'] = problem_to_reset

    if student:
        response_payload['student'] = student_identifier
        instructor_task.api.submit_rescore_problem_for_student(
            request, course_id, module_state_key, student)
        response_payload['task'] = 'created'
    elif all_students:
        instructor_task.api.submit_rescore_problem_for_all_students(
            request, course_id, module_state_key)
        response_payload['task'] = 'created'
    else:
        return HttpResponseBadRequest()

    return JsonResponse(response_payload)
コード例 #15
0
ファイル: api.py プロジェクト: stargao2000/edx-platform
def rescore_problem(request, course_id):
    """
    Starts a background process a students attempts counter. Optionally deletes student state for a problem.
    Limited to instructor access.

    Takes either of the following query paremeters
        - problem_to_reset is a urlname of a problem
        - unique_student_identifier is an email or username
        - all_students is a boolean

    all_students and unique_student_identifier cannot both be present.
    """
    problem_to_reset = strip_if_string(request.GET.get('problem_to_reset'))
    student_identifier = request.GET.get('unique_student_identifier', None)
    student = None
    if student_identifier is not None:
        student = get_student_from_identifier(student_identifier)

    all_students = request.GET.get('all_students') in ['true', 'True', True]

    if not (problem_to_reset and (all_students or student)):
        return HttpResponseBadRequest("Missing query parameters.")

    if all_students and student:
        return HttpResponseBadRequest(
            "Cannot rescore with all_students and unique_student_identifier."
        )

    module_state_key = _msk_from_problem_urlname(course_id, problem_to_reset)

    response_payload = {}
    response_payload['problem_to_reset'] = problem_to_reset

    if student:
        response_payload['student'] = student_identifier
        instructor_task.api.submit_rescore_problem_for_student(request, course_id, module_state_key, student)
        response_payload['task'] = 'created'
    elif all_students:
        instructor_task.api.submit_rescore_problem_for_all_students(request, course_id, module_state_key)
        response_payload['task'] = 'created'
    else:
        return HttpResponseBadRequest()

    return JsonResponse(response_payload)
コード例 #16
0
ファイル: api.py プロジェクト: stargao2000/edx-platform
def get_student_progress_url(request, course_id):
    """
    Get the progress url of a student.
    Limited to staff access.

    Takes query paremeter unique_student_identifier and if the student exists
    returns e.g. {
        'progress_url': '/../...'
    }
    """
    user = get_student_from_identifier(request.GET.get('unique_student_identifier'))

    progress_url = reverse('student_progress', kwargs={'course_id': course_id, 'student_id': user.id})

    response_payload = {
        'course_id': course_id,
        'progress_url': progress_url,
    }
    return JsonResponse(response_payload)
コード例 #17
0
def get_student_progress_url(request, course_id):
    """
    Get the progress url of a student.
    Limited to staff access.

    Takes query paremeter unique_student_identifier and if the student exists
    returns e.g. {
        'progress_url': '/../...'
    }
    """
    user = get_student_from_identifier(request.GET.get('unique_student_identifier'))

    progress_url = reverse('student_progress', kwargs={'course_id': course_id, 'student_id': user.id})

    response_payload = {
        'course_id': course_id,
        'progress_url': progress_url,
    }
    return JsonResponse(response_payload)
コード例 #18
0
def ccx_student_management(request, course, ccx=None):
    """Manage the enrollment of individual students in a CCX
    """
    if not ccx:
        raise Http404

    action = request.POST.get('student-action', None)
    student_id = request.POST.get('student-id', '')
    user = email = None
    error_message = ""
    course_key = CCXLocator.from_course_locator(course.id, ccx.id)
    try:
        user = get_student_from_identifier(student_id)
    except User.DoesNotExist:
        email = student_id
        error_message = validate_student_email(email)
        if email and not error_message:
            error_message = _(
                'Could not find a user with name or email "{email}" ').format(
                    email=email)
    else:
        email = user.email
        error_message = validate_student_email(email)

    if error_message is None:
        if action == 'add':
            # by decree, no emails sent to students added this way
            # by decree, any students added this way are auto_enrolled
            enroll_email(course_key,
                         email,
                         auto_enroll=True,
                         email_students=False)
        elif action == 'revoke':
            unenroll_email(course_key, email, email_students=False)
    else:
        messages.error(request, error_message)

    url = reverse('ccx_coach_dashboard', kwargs={'course_id': course_key})
    return redirect(url)
コード例 #19
0
ファイル: views.py プロジェクト: ovnicraft/fun-apps
def modify_special_forum_contributors(request, course_id):

    unique_student_identifier = request.GET.get("unique_student_identifier")
    rolename = request.GET.get("rolename")
    action = request.GET.get("action")

    course_id = _check_rights(course_id, request.user, rolename)
    course = get_course_by_id(course_id)
    _check_custom_roles(course_id)

    user = get_student_from_identifier(unique_student_identifier)
    target_is_instructor = has_access(user, "instructor", course)
    # cannot revoke instructor
    if target_is_instructor and action == "revoke" and rolename == FORUM_ROLE_ADMINISTRATOR:
        return HttpResponseBadRequest("Cannot revoke instructor forum admin privileges.")
    try:
        update_forum_role(course_id, user, rolename, action)
    except Role.DoesNotExist:
        return HttpResponseBadRequest("Role does not exist.")

    response_payload = {"course_id": course_id.to_deprecated_string(), "action": action}
    return JsonResponse(response_payload)
コード例 #20
0
def list_instructor_tasks(request, course_id):
    """
    List instructor tasks.
    Limited to instructor access.

    Takes optional query paremeters.
        - With no arguments, lists running tasks.
        - `problem_urlname` lists task history for problem
        - `problem_urlname` and `unique_student_identifier` lists task
            history for problem AND student (intersection)
    """
    problem_urlname = strip_if_string(request.GET.get('problem_urlname', False))
    student = request.GET.get('unique_student_identifier', None)
    if student is not None:
        student = get_student_from_identifier(student)

    if student and not problem_urlname:
        return HttpResponseBadRequest(
            "unique_student_identifier must accompany problem_urlname"
        )

    if problem_urlname:
        module_state_key = _msk_from_problem_urlname(course_id, problem_urlname)
        if student:
            tasks = instructor_task.api.get_instructor_task_history(course_id, module_state_key, student)
        else:
            tasks = instructor_task.api.get_instructor_task_history(course_id, module_state_key)
    else:
        tasks = instructor_task.api.get_running_instructor_tasks(course_id)

    def extract_task_features(task):
        """ Convert task to dict for json rendering """
        features = ['task_type', 'task_input', 'task_id', 'requester', 'created', 'task_state']
        return dict((feature, str(getattr(task, feature))) for feature in features)

    response_payload = {
        'tasks': map(extract_task_features, tasks),
    }
    return JsonResponse(response_payload)
コード例 #21
0
def list_instructor_tasks(request, course_id):
    """
    List instructor tasks.

    Takes optional query paremeters.
        - With no arguments, lists running tasks.
        - `problem_urlname` lists task history for problem
        - `problem_urlname` and `unique_student_identifier` lists task
            history for problem AND student (intersection)
    """
    problem_urlname = strip_if_string(request.GET.get('problem_urlname',
                                                      False))
    student = request.GET.get('unique_student_identifier', None)
    if student is not None:
        student = get_student_from_identifier(student)

    if student and not problem_urlname:
        return HttpResponseBadRequest(
            "unique_student_identifier must accompany problem_urlname")

    if problem_urlname:
        module_state_key = _msk_from_problem_urlname(course_id,
                                                     problem_urlname)
        if student:
            # Specifying for a single student's history on this problem
            tasks = instructor_task.api.get_instructor_task_history(
                course_id, module_state_key, student)
        else:
            # Specifying for single problem's history
            tasks = instructor_task.api.get_instructor_task_history(
                course_id, module_state_key)
    else:
        # If no problem or student, just get currently running tasks
        tasks = instructor_task.api.get_running_instructor_tasks(course_id)

    response_payload = {
        'tasks': map(extract_task_features, tasks),
    }
    return JsonResponse(response_payload)
コード例 #22
0
ファイル: api.py プロジェクト: stargao2000/edx-platform
def list_instructor_tasks(request, course_id):
    """
    List instructor tasks.

    Takes optional query paremeters.
        - With no arguments, lists running tasks.
        - `problem_urlname` lists task history for problem
        - `problem_urlname` and `unique_student_identifier` lists task
            history for problem AND student (intersection)
    """
    problem_urlname = strip_if_string(request.GET.get('problem_urlname', False))
    student = request.GET.get('unique_student_identifier', None)
    if student is not None:
        student = get_student_from_identifier(student)

    if student and not problem_urlname:
        return HttpResponseBadRequest(
            "unique_student_identifier must accompany problem_urlname"
        )

    if problem_urlname:
        module_state_key = _msk_from_problem_urlname(course_id, problem_urlname)
        if student:
            # Specifying for a single student's history on this problem
            tasks = instructor_task.api.get_instructor_task_history(course_id, module_state_key, student)
        else:
            # Specifying for single problem's history
            tasks = instructor_task.api.get_instructor_task_history(course_id, module_state_key)
    else:
        # If no problem or student, just get currently running tasks
        tasks = instructor_task.api.get_running_instructor_tasks(course_id)

    response_payload = {
        'tasks': map(extract_task_features, tasks),
    }
    return JsonResponse(response_payload)
コード例 #23
0
ファイル: api.py プロジェクト: g-vidal/edx-platform
def list_instructor_tasks(request, course_id):
    """
    List instructor tasks.
    Limited to instructor access.

    Takes optional query paremeters.
        - With no arguments, lists running tasks.
        - `problem_urlname` lists task history for problem
        - `problem_urlname` and `unique_student_identifier` lists task
            history for problem AND student (intersection)
    """
    problem_urlname = strip_if_string(request.GET.get('problem_urlname', False))
    student = request.GET.get('unique_student_identifier', None)
    if student is not None:
        student = get_student_from_identifier(student)

    if student and not problem_urlname:
        return HttpResponseBadRequest(
            "unique_student_identifier must accompany problem_urlname"
        )

    if problem_urlname:
        module_state_key = _msk_from_problem_urlname(course_id, problem_urlname)
        if student:
            tasks = instructor_task.api.get_instructor_task_history(course_id, module_state_key, student)
        else:
            tasks = instructor_task.api.get_instructor_task_history(course_id, module_state_key)
    else:
        tasks = instructor_task.api.get_running_instructor_tasks(course_id)

    def extract_task_features(task):
        """
        Convert task to dict for json rendering.
        Expects tasks have the following features:
        * task_type (str, type of task)
        * task_input (dict, input(s) to the task)
        * task_id (str, celery id of the task)
        * requester (str, username who submitted the task)
        * task_state (str, state of task eg PROGRESS, COMPLETED)
        * created (datetime, when the task was completed)
        * task_output (optional)
        """
        # Pull out information from the task
        features = ['task_type', 'task_input', 'task_id', 'requester', 'task_state']
        task_feature_dict = {feature: str(getattr(task, feature)) for feature in features}
        # Some information (created, duration, status, task message) require additional formatting
        task_feature_dict['created'] = task.created.isoformat()

        # Get duration info, if known
        duration_sec = 'unknown'
        if hasattr(task, 'task_output') and task.task_output is not None:
            try:
                task_output = json.loads(task.task_output)
            except ValueError:
                log.error("Could not parse task output as valid json; task output: %s", task.task_output)
            else:
                if 'duration_ms' in task_output:
                    duration_sec = int(task_output['duration_ms'] / 1000.0)
        task_feature_dict['duration_sec'] = duration_sec

        # Get progress status message & success information
        success, task_message = get_task_completion_info(task)
        status = _("Complete") if success else _("Incomplete")
        task_feature_dict['status'] = status
        task_feature_dict['task_message'] = task_message

        return task_feature_dict

    response_payload = {
        'tasks': map(extract_task_features, tasks),
    }
    return JsonResponse(response_payload)
コード例 #24
0
ファイル: api.py プロジェクト: sorenbechdk/edx-platform
def list_instructor_tasks(request, course_id):
    """
    List instructor tasks.
    Limited to instructor access.

    Takes optional query paremeters.
        - With no arguments, lists running tasks.
        - `problem_urlname` lists task history for problem
        - `problem_urlname` and `unique_student_identifier` lists task
            history for problem AND student (intersection)
    """
    problem_urlname = strip_if_string(request.GET.get('problem_urlname',
                                                      False))
    student = request.GET.get('unique_student_identifier', None)
    if student is not None:
        student = get_student_from_identifier(student)

    if student and not problem_urlname:
        return HttpResponseBadRequest(
            "unique_student_identifier must accompany problem_urlname")

    if problem_urlname:
        module_state_key = _msk_from_problem_urlname(course_id,
                                                     problem_urlname)
        if student:
            tasks = instructor_task.api.get_instructor_task_history(
                course_id, module_state_key, student)
        else:
            tasks = instructor_task.api.get_instructor_task_history(
                course_id, module_state_key)
    else:
        tasks = instructor_task.api.get_running_instructor_tasks(course_id)

    def extract_task_features(task):
        """
        Convert task to dict for json rendering.
        Expects tasks have the following features:
        * task_type (str, type of task)
        * task_input (dict, input(s) to the task)
        * task_id (str, celery id of the task)
        * requester (str, username who submitted the task)
        * task_state (str, state of task eg PROGRESS, COMPLETED)
        * created (datetime, when the task was completed)
        * task_output (optional)
        """
        # Pull out information from the task
        features = [
            'task_type', 'task_input', 'task_id', 'requester', 'task_state'
        ]
        task_feature_dict = {
            feature: str(getattr(task, feature))
            for feature in features
        }
        # Some information (created, duration, status, task message) require additional formatting
        task_feature_dict['created'] = task.created.isoformat()

        # Get duration info, if known
        duration_sec = 'unknown'
        if hasattr(task, 'task_output') and task.task_output is not None:
            try:
                task_output = json.loads(task.task_output)
            except ValueError:
                log.error(
                    "Could not parse task output as valid json; task output: %s",
                    task.task_output)
            else:
                if 'duration_ms' in task_output:
                    duration_sec = int(task_output['duration_ms'] / 1000.0)
        task_feature_dict['duration_sec'] = duration_sec

        # Get progress status message & success information
        success, task_message = get_task_completion_info(task)
        status = _("Complete") if success else _("Incomplete")
        task_feature_dict['status'] = status
        task_feature_dict['task_message'] = task_message

        return task_feature_dict

    response_payload = {
        'tasks': map(extract_task_features, tasks),
    }
    return JsonResponse(response_payload)
コード例 #25
0
def reset_student_attempts(request, course_id):
    """

    Resets a students attempts counter or starts a task to reset all students
    attempts counters. Optionally deletes student state for a problem. Limited
    to staff access. Some sub-methods limited to instructor access.

    Takes some of the following query paremeters
        - problem_to_reset is a urlname of a problem
        - unique_student_identifier is an email or username
        - all_students is a boolean
            requires instructor access
            mutually exclusive with delete_module
            mutually exclusive with delete_module
        - delete_module is a boolean
            requires instructor access
            mutually exclusive with all_students
    """
    course = get_course_with_access(request.user,
                                    course_id,
                                    'staff',
                                    depth=None)

    problem_to_reset = strip_if_string(request.GET.get('problem_to_reset'))
    student_identifier = request.GET.get('unique_student_identifier', None)
    student = None
    if student_identifier is not None:
        student = get_student_from_identifier(student_identifier)
    all_students = request.GET.get('all_students',
                                   False) in ['true', 'True', True]
    delete_module = request.GET.get('delete_module',
                                    False) in ['true', 'True', True]

    # parameter combinations
    if all_students and student:
        return HttpResponseBadRequest(
            "all_students and unique_student_identifier are mutually exclusive."
        )
    if all_students and delete_module:
        return HttpResponseBadRequest(
            "all_students and delete_module are mutually exclusive.")

    # instructor authorization
    if all_students or delete_module:
        if not has_access(request.user, course, 'instructor'):
            return HttpResponseForbidden("Requires instructor access.")

    module_state_key = _msk_from_problem_urlname(course_id, problem_to_reset)

    response_payload = {}
    response_payload['problem_to_reset'] = problem_to_reset

    if student:
        try:
            enrollment.reset_student_attempts(course_id,
                                              student,
                                              module_state_key,
                                              delete_module=delete_module)
        except StudentModule.DoesNotExist:
            return HttpResponseBadRequest("Module does not exist.")
        response_payload['student'] = student_identifier
    elif all_students:
        instructor_task.api.submit_reset_problem_attempts_for_all_students(
            request, course_id, module_state_key)
        response_payload['task'] = 'created'
        response_payload['student'] = 'All Students'
    else:
        return HttpResponseBadRequest()

    return JsonResponse(response_payload)
コード例 #26
0
ファイル: api.py プロジェクト: stargao2000/edx-platform
def reset_student_attempts(request, course_id):
    """

    Resets a students attempts counter or starts a task to reset all students
    attempts counters. Optionally deletes student state for a problem. Limited
    to staff access. Some sub-methods limited to instructor access.

    Takes some of the following query paremeters
        - problem_to_reset is a urlname of a problem
        - unique_student_identifier is an email or username
        - all_students is a boolean
            requires instructor access
            mutually exclusive with delete_module
            mutually exclusive with delete_module
        - delete_module is a boolean
            requires instructor access
            mutually exclusive with all_students
    """
    course = get_course_with_access(
        request.user, course_id, 'staff', depth=None
    )

    problem_to_reset = strip_if_string(request.GET.get('problem_to_reset'))
    student_identifier = request.GET.get('unique_student_identifier', None)
    student = None
    if student_identifier is not None:
        student = get_student_from_identifier(student_identifier)
    all_students = request.GET.get('all_students', False) in ['true', 'True', True]
    delete_module = request.GET.get('delete_module', False) in ['true', 'True', True]

    # parameter combinations
    if all_students and student:
        return HttpResponseBadRequest(
            "all_students and unique_student_identifier are mutually exclusive."
        )
    if all_students and delete_module:
        return HttpResponseBadRequest(
            "all_students and delete_module are mutually exclusive."
        )

    # instructor authorization
    if all_students or delete_module:
        if not has_access(request.user, course, 'instructor'):
            return HttpResponseForbidden("Requires instructor access.")

    module_state_key = _msk_from_problem_urlname(course_id, problem_to_reset)

    response_payload = {}
    response_payload['problem_to_reset'] = problem_to_reset

    if student:
        try:
            enrollment.reset_student_attempts(course_id, student, module_state_key, delete_module=delete_module)
        except StudentModule.DoesNotExist:
            return HttpResponseBadRequest("Module does not exist.")
        response_payload['student'] = student_identifier
    elif all_students:
        instructor_task.api.submit_reset_problem_attempts_for_all_students(request, course_id, module_state_key)
        response_payload['task'] = 'created'
        response_payload['student'] = 'All Students'
    else:
        return HttpResponseBadRequest()

    return JsonResponse(response_payload)