|
|
|
|
@@ -37,7 +37,8 @@ from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthenticat
|
|
|
|
|
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
|
|
|
|
|
from opaque_keys import InvalidKeyError
|
|
|
|
|
from opaque_keys.edx.keys import CourseKey, UsageKey
|
|
|
|
|
from rest_framework import permissions, status
|
|
|
|
|
from rest_framework import status
|
|
|
|
|
from rest_framework.permissions import IsAuthenticated, IsAdminUser
|
|
|
|
|
from rest_framework.response import Response
|
|
|
|
|
from rest_framework.views import APIView
|
|
|
|
|
from six import StringIO, text_type
|
|
|
|
|
@@ -135,18 +136,8 @@ from util.json_request import JsonResponse, JsonResponseBadRequest
|
|
|
|
|
from util.views import require_global_staff
|
|
|
|
|
from xmodule.modulestore.django import modulestore
|
|
|
|
|
|
|
|
|
|
from ..permissions import (
|
|
|
|
|
ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM,
|
|
|
|
|
ASSIGN_TO_COHORTS,
|
|
|
|
|
EDIT_COURSE_ACCESS,
|
|
|
|
|
EDIT_FORUM_ROLES,
|
|
|
|
|
EDIT_INVOICE_VALIDATION,
|
|
|
|
|
ENABLE_CERTIFICATE_GENERATION,
|
|
|
|
|
GENERATE_BULK_CERTIFICATE_EXCEPTIONS,
|
|
|
|
|
GENERATE_CERTIFICATE_EXCEPTIONS,
|
|
|
|
|
GIVE_STUDENT_EXTENSION,
|
|
|
|
|
VIEW_ISSUED_CERTIFICATES
|
|
|
|
|
)
|
|
|
|
|
from .. import permissions
|
|
|
|
|
|
|
|
|
|
from .tools import (
|
|
|
|
|
dump_module_extensions,
|
|
|
|
|
dump_student_extensions,
|
|
|
|
|
@@ -231,36 +222,6 @@ def require_post_params(*args, **kwargs):
|
|
|
|
|
return decorator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def require_level(level, perm=None):
|
|
|
|
|
"""
|
|
|
|
|
Decorator with argument that requires an access level of the requesting
|
|
|
|
|
user. If the requirement is not satisfied, returns an
|
|
|
|
|
HttpResponseForbidden (403).
|
|
|
|
|
|
|
|
|
|
Assumes that request is in args[0].
|
|
|
|
|
Assumes that course_id is in kwargs['course_id'].
|
|
|
|
|
|
|
|
|
|
`level` is in ['instructor', 'staff']
|
|
|
|
|
if `level` is 'staff', instructors will also be allowed, even
|
|
|
|
|
if they are not in the staff group.
|
|
|
|
|
"""
|
|
|
|
|
if level not in ['instructor', 'staff']:
|
|
|
|
|
raise ValueError(u"unrecognized level '{}'".format(level))
|
|
|
|
|
|
|
|
|
|
def decorator(func): # pylint: disable=missing-docstring
|
|
|
|
|
def wrapped(*args, **kwargs):
|
|
|
|
|
request = args[0]
|
|
|
|
|
course = get_course_by_id(CourseKey.from_string(kwargs['course_id']))
|
|
|
|
|
|
|
|
|
|
if has_access(request.user, level, course) and \
|
|
|
|
|
((perm and request.user.has_perm(perm, course.id)) or not perm):
|
|
|
|
|
return func(*args, **kwargs)
|
|
|
|
|
else:
|
|
|
|
|
return HttpResponseForbidden()
|
|
|
|
|
return wrapped
|
|
|
|
|
return decorator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def require_course_permission(permission):
|
|
|
|
|
"""
|
|
|
|
|
Decorator with argument that requires a specific permission of the requesting
|
|
|
|
|
@@ -342,7 +303,7 @@ COUNTRY_INDEX = 3
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.CAN_ENROLL)
|
|
|
|
|
def register_and_enroll_students(request, course_id): # pylint: disable=too-many-statements
|
|
|
|
|
"""
|
|
|
|
|
Create new account and Enroll students in this course.
|
|
|
|
|
@@ -658,7 +619,7 @@ def create_and_enroll_user(email, username, name, country, password, course_id,
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.CAN_ENROLL)
|
|
|
|
|
@require_post_params(action="enroll or unenroll", identifiers="stringified list of emails and/or usernames")
|
|
|
|
|
def students_update_enrollment(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -826,7 +787,7 @@ def students_update_enrollment(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('instructor')
|
|
|
|
|
@require_course_permission(permissions.CAN_BETATEST)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
@require_post_params(
|
|
|
|
|
identifiers="stringified list of emails and/or usernames",
|
|
|
|
|
@@ -910,7 +871,7 @@ def bulk_beta_modify_access(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_course_permission(EDIT_COURSE_ACCESS)
|
|
|
|
|
@require_course_permission(permissions.EDIT_COURSE_ACCESS)
|
|
|
|
|
@require_post_params(
|
|
|
|
|
unique_student_identifier="email or username of user to change access",
|
|
|
|
|
rolename="'instructor', 'staff', 'beta', or 'ccx_coach'",
|
|
|
|
|
@@ -991,7 +952,7 @@ def modify_access(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('instructor')
|
|
|
|
|
@require_course_permission(permissions.EDIT_COURSE_ACCESS)
|
|
|
|
|
@require_post_params(rolename="'instructor', 'staff', or 'beta'")
|
|
|
|
|
def list_course_role_members(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1045,7 +1006,7 @@ def list_course_role_members(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def get_problem_responses(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1085,15 +1046,17 @@ def get_problem_responses(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
def get_grading_config(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
Respond with json which contains a html formatted grade summary.
|
|
|
|
|
"""
|
|
|
|
|
course_id = CourseKey.from_string(course_id)
|
|
|
|
|
course = get_course_with_access(
|
|
|
|
|
request.user, 'staff', course_id, depth=None
|
|
|
|
|
)
|
|
|
|
|
# course = get_course_with_access(
|
|
|
|
|
# request.user, 'staff', course_id, depth=None
|
|
|
|
|
# )
|
|
|
|
|
course = get_course_by_id(course_id)
|
|
|
|
|
|
|
|
|
|
grading_config_summary = instructor_analytics.basic.dump_grading_context(course)
|
|
|
|
|
|
|
|
|
|
response_payload = {
|
|
|
|
|
@@ -1105,7 +1068,7 @@ def get_grading_config(request, course_id):
|
|
|
|
|
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
def get_sale_records(request, course_id, csv=False): # pylint: disable=unused-argument, redefined-outer-name
|
|
|
|
|
"""
|
|
|
|
|
return the summary of all sales records for a particular course
|
|
|
|
|
@@ -1136,7 +1099,7 @@ def get_sale_records(request, course_id, csv=False): # pylint: disable=unused-a
|
|
|
|
|
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
def get_sale_order_records(request, course_id): # pylint: disable=unused-argument
|
|
|
|
|
"""
|
|
|
|
|
return the summary of all sales records for a particular course
|
|
|
|
|
@@ -1176,7 +1139,7 @@ def get_sale_order_records(request, course_id): # pylint: disable=unused-argume
|
|
|
|
|
return instructor_analytics.csvs.create_csv_response("e-commerce_sale_order_records.csv", csv_columns, datarows)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@require_course_permission(EDIT_INVOICE_VALIDATION)
|
|
|
|
|
@require_course_permission(permissions.EDIT_INVOICE_VALIDATION)
|
|
|
|
|
@require_POST
|
|
|
|
|
def sale_validation(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1243,7 +1206,7 @@ def re_validate_invoice(obj_invoice):
|
|
|
|
|
@transaction.non_atomic_requests
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_course_permission(VIEW_ISSUED_CERTIFICATES)
|
|
|
|
|
@require_course_permission(permissions.VIEW_ISSUED_CERTIFICATES)
|
|
|
|
|
def get_issued_certificates(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
Responds with JSON if CSV is not required. contains a list of issued certificates.
|
|
|
|
|
@@ -1284,7 +1247,7 @@ def get_issued_certificates(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def get_students_features(request, course_id, csv=False): # pylint: disable=redefined-outer-name
|
|
|
|
|
"""
|
|
|
|
|
@@ -1381,7 +1344,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def get_students_who_may_enroll(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1428,7 +1391,7 @@ def _cohorts_csv_validator(file_storage, file_to_validate):
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_POST
|
|
|
|
|
@require_course_permission(ASSIGN_TO_COHORTS)
|
|
|
|
|
@require_course_permission(permissions.ASSIGN_TO_COHORTS)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def add_users_to_cohorts(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1474,7 +1437,7 @@ class CohortCSV(DeveloperErrorViewMixin, APIView):
|
|
|
|
|
BearerAuthenticationAllowInactiveUser,
|
|
|
|
|
SessionAuthenticationAllowInactiveUser,
|
|
|
|
|
)
|
|
|
|
|
permission_classes = (permissions.IsAuthenticated, permissions.IsAdminUser)
|
|
|
|
|
permission_classes = (IsAuthenticated, IsAdminUser)
|
|
|
|
|
|
|
|
|
|
def post(self, request, course_key_string):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1498,7 +1461,7 @@ class CohortCSV(DeveloperErrorViewMixin, APIView):
|
|
|
|
|
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.VIEW_COUPONS)
|
|
|
|
|
def get_coupon_codes(request, course_id): # pylint: disable=unused-argument
|
|
|
|
|
"""
|
|
|
|
|
Respond with csv which contains a summary of all Active Coupons.
|
|
|
|
|
@@ -1529,7 +1492,7 @@ def get_coupon_codes(request, course_id): # pylint: disable=unused-argument
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.ENROLLMENT_REPORT)
|
|
|
|
|
@require_finance_admin
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def get_enrollment_report(request, course_id):
|
|
|
|
|
@@ -1548,7 +1511,7 @@ def get_enrollment_report(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.ENROLLMENT_REPORT)
|
|
|
|
|
@require_finance_admin
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def get_exec_summary_report(request, course_id):
|
|
|
|
|
@@ -1567,7 +1530,7 @@ def get_exec_summary_report(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.ENROLLMENT_REPORT)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def get_course_survey_results(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1585,7 +1548,7 @@ def get_course_survey_results(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.EXAM_RESULTS)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def get_proctored_exam_results(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1674,7 +1637,7 @@ def random_code_generator():
|
|
|
|
|
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.VIEW_COUPONS)
|
|
|
|
|
@require_POST
|
|
|
|
|
def get_registration_codes(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1869,7 +1832,7 @@ def generate_registration_codes(request, course_id):
|
|
|
|
|
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.VIEW_COUPONS)
|
|
|
|
|
@require_POST
|
|
|
|
|
def active_registration_codes(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1900,7 +1863,7 @@ def active_registration_codes(request, course_id):
|
|
|
|
|
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.VIEW_COUPONS)
|
|
|
|
|
@require_POST
|
|
|
|
|
def spent_registration_codes(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -1931,7 +1894,7 @@ def spent_registration_codes(request, course_id):
|
|
|
|
|
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
def get_anon_ids(request, course_id): # pylint: disable=unused-argument
|
|
|
|
|
"""
|
|
|
|
|
Respond with 2-column CSV output of user-id, anonymized-user-id
|
|
|
|
|
@@ -1969,7 +1932,7 @@ def get_anon_ids(request, course_id): # pylint: disable=unused-argument
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.CAN_ENROLL)
|
|
|
|
|
@require_post_params(
|
|
|
|
|
unique_student_identifier="email or username of student for whom to get enrollment status"
|
|
|
|
|
)
|
|
|
|
|
@@ -2026,7 +1989,7 @@ def get_student_enrollment_status(request, course_id):
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.ENROLLMENT_REPORT)
|
|
|
|
|
@require_post_params(
|
|
|
|
|
unique_student_identifier="email or username of student for whom to get progress url"
|
|
|
|
|
)
|
|
|
|
|
@@ -2057,7 +2020,7 @@ def get_student_progress_url(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.GIVE_STUDENT_EXTENSION)
|
|
|
|
|
@require_post_params(
|
|
|
|
|
problem_to_reset="problem urlname to reset"
|
|
|
|
|
)
|
|
|
|
|
@@ -2144,7 +2107,7 @@ def reset_student_attempts(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.GIVE_STUDENT_EXTENSION)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def reset_student_attempts_for_entrance_exam(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2219,7 +2182,7 @@ def reset_student_attempts_for_entrance_exam(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.OVERRIDE_GRADES)
|
|
|
|
|
@require_post_params(problem_to_reset="problem urlname to reset")
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def rescore_problem(request, course_id):
|
|
|
|
|
@@ -2295,7 +2258,7 @@ def rescore_problem(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.OVERRIDE_GRADES)
|
|
|
|
|
@require_post_params(problem_to_reset="problem urlname to reset", score='overriding score')
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def override_problem_score(request, course_id):
|
|
|
|
|
@@ -2352,7 +2315,7 @@ def override_problem_score(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('instructor')
|
|
|
|
|
@require_course_permission(permissions.RESCORE_EXAMS)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def rescore_entrance_exam(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2409,7 +2372,7 @@ def rescore_entrance_exam(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.EMAIL)
|
|
|
|
|
def list_background_email_tasks(request, course_id): # pylint: disable=unused-argument
|
|
|
|
|
"""
|
|
|
|
|
List background email tasks.
|
|
|
|
|
@@ -2431,7 +2394,7 @@ def list_background_email_tasks(request, course_id): # pylint: disable=unused-a
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.EMAIL)
|
|
|
|
|
def list_email_content(request, course_id): # pylint: disable=unused-argument
|
|
|
|
|
"""
|
|
|
|
|
List the content of bulk emails sent
|
|
|
|
|
@@ -2450,7 +2413,7 @@ def list_email_content(request, course_id): # pylint: disable=unused-argument
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.SHOW_TASKS)
|
|
|
|
|
def list_instructor_tasks(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
List instructor tasks.
|
|
|
|
|
@@ -2496,7 +2459,7 @@ def list_instructor_tasks(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.SHOW_TASKS)
|
|
|
|
|
def list_entrance_exam_instructor_tasks(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
List entrance exam related instructor tasks.
|
|
|
|
|
@@ -2538,7 +2501,7 @@ def list_entrance_exam_instructor_tasks(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
def list_report_downloads(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
List grade CSV files that are available for download for this course.
|
|
|
|
|
@@ -2562,7 +2525,7 @@ def list_report_downloads(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
@require_finance_admin
|
|
|
|
|
def list_financial_report_downloads(_request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2584,7 +2547,7 @@ def list_financial_report_downloads(_request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def export_ora2_data(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2602,7 +2565,7 @@ def export_ora2_data(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def calculate_grades_csv(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2620,7 +2583,7 @@ def calculate_grades_csv(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff', perm='student.can_research')
|
|
|
|
|
@require_course_permission(permissions.CAN_RESEARCH)
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def problem_grade_report(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2641,7 +2604,7 @@ def problem_grade_report(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.CAN_ENROLL)
|
|
|
|
|
@require_post_params('rolename')
|
|
|
|
|
def list_forum_members(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2713,7 +2676,7 @@ def list_forum_members(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.EMAIL)
|
|
|
|
|
@require_post_params(send_to="sending to whom", subject="subject line", message="message text")
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def send_email(request, course_id):
|
|
|
|
|
@@ -2789,7 +2752,7 @@ def send_email(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_course_permission(EDIT_FORUM_ROLES)
|
|
|
|
|
@require_course_permission(permissions.EDIT_FORUM_ROLES)
|
|
|
|
|
@require_post_params(
|
|
|
|
|
unique_student_identifier="email or username of user to change access",
|
|
|
|
|
rolename="the forum role",
|
|
|
|
|
@@ -2882,7 +2845,7 @@ def _display_unit(unit):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_course_permission(GIVE_STUDENT_EXTENSION)
|
|
|
|
|
@require_course_permission(permissions.GIVE_STUDENT_EXTENSION)
|
|
|
|
|
@require_post_params('student', 'url', 'due_datetime')
|
|
|
|
|
def change_due_date(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2906,7 +2869,7 @@ def change_due_date(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_course_permission(GIVE_STUDENT_EXTENSION)
|
|
|
|
|
@require_course_permission(permissions.GIVE_STUDENT_EXTENSION)
|
|
|
|
|
@require_post_params('student', 'url')
|
|
|
|
|
def reset_due_date(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2935,7 +2898,7 @@ def reset_due_date(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.GIVE_STUDENT_EXTENSION)
|
|
|
|
|
@require_post_params('url')
|
|
|
|
|
def show_unit_extensions(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -2950,7 +2913,7 @@ def show_unit_extensions(request, course_id):
|
|
|
|
|
@require_POST
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_level('staff')
|
|
|
|
|
@require_course_permission(permissions.GIVE_STUDENT_EXTENSION)
|
|
|
|
|
@require_post_params('student')
|
|
|
|
|
def show_student_extensions(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -3017,7 +2980,7 @@ def generate_example_certificates(request, course_id=None): # pylint: disable=u
|
|
|
|
|
return redirect(_instructor_dash_url(course_key, section='certificates'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@require_course_permission(ENABLE_CERTIFICATE_GENERATION)
|
|
|
|
|
@require_course_permission(permissions.ENABLE_CERTIFICATE_GENERATION)
|
|
|
|
|
@require_POST
|
|
|
|
|
def enable_certificate_generation(request, course_id=None):
|
|
|
|
|
"""Enable/disable self-generated certificates for a course.
|
|
|
|
|
@@ -3037,7 +3000,7 @@ def enable_certificate_generation(request, course_id=None):
|
|
|
|
|
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_course_permission(ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM)
|
|
|
|
|
@require_course_permission(permissions.ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM)
|
|
|
|
|
@require_POST
|
|
|
|
|
def mark_student_can_skip_entrance_exam(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
@@ -3301,7 +3264,7 @@ def get_student(username_or_email, course_key):
|
|
|
|
|
@transaction.non_atomic_requests
|
|
|
|
|
@ensure_csrf_cookie
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_course_permission(GENERATE_CERTIFICATE_EXCEPTIONS)
|
|
|
|
|
@require_course_permission(permissions.GENERATE_CERTIFICATE_EXCEPTIONS)
|
|
|
|
|
@require_POST
|
|
|
|
|
@common_exceptions_400
|
|
|
|
|
def generate_certificate_exceptions(request, course_id, generate_for=None):
|
|
|
|
|
@@ -3343,7 +3306,7 @@ def generate_certificate_exceptions(request, course_id, generate_for=None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
|
|
|
|
@require_course_permission(GENERATE_BULK_CERTIFICATE_EXCEPTIONS)
|
|
|
|
|
@require_course_permission(permissions.GENERATE_BULK_CERTIFICATE_EXCEPTIONS)
|
|
|
|
|
@require_POST
|
|
|
|
|
def generate_bulk_certificate_exceptions(request, course_id):
|
|
|
|
|
"""
|
|
|
|
|
|