Make course ids and usage ids opaque to LMS and Studio [partial commit]

This commit updates common/djangoapps.

These keys are now objects with a limited interface, and the particular
internal representation is managed by the data storage layer (the
modulestore).

For the LMS, there should be no outward-facing changes to the system.
The keys are, for now, a change to internal representation only. For
Studio, the new serialized form of the keys is used in urls, to allow
for further migration in the future.

Co-Author: Andy Armstrong <andya@edx.org>
Co-Author: Christina Roberts <christina@edx.org>
Co-Author: David Baumgold <db@edx.org>
Co-Author: Diana Huang <dkh@edx.org>
Co-Author: Don Mitchell <dmitchell@edx.org>
Co-Author: Julia Hansbrough <julia@edx.org>
Co-Author: Nimisha Asthagiri <nasthagiri@edx.org>
Co-Author: Sarina Canelake <sarina@edx.org>

[LMS-2370]
This commit is contained in:
Calen Pennington
2014-04-30 10:17:43 -04:00
parent 7852906ce0
commit e2bfcf2a36
42 changed files with 603 additions and 330 deletions

View File

@@ -55,6 +55,7 @@ from dark_lang.models import DarkLangConfig
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.locations import SlashSeparatedCourseKey
from xmodule.modulestore import XML_MODULESTORE_TYPE, Location
from collections import namedtuple
@@ -132,8 +133,7 @@ def index(request, extra_context={}, user=AnonymousUser()):
def course_from_id(course_id):
"""Return the CourseDescriptor corresponding to this course_id"""
course_loc = CourseDescriptor.id_to_location(course_id)
return modulestore().get_instance(course_id, course_loc)
return modulestore().get_course(course_id)
day_pattern = re.compile(r'\s\d+,\s')
multimonth_pattern = re.compile(r'\s?\-\s?\S+\s')
@@ -269,8 +269,8 @@ def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set):
a student's dashboard.
"""
for enrollment in CourseEnrollment.enrollments_for_user(user):
try:
course = course_from_id(enrollment.course_id)
course = course_from_id(enrollment.course_id)
if course:
# if we are in a Microsite, then filter out anything that is not
# attributed (by ORG) to that Microsite
@@ -282,7 +282,7 @@ def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set):
continue
yield (course, enrollment)
except ItemNotFoundError:
else:
log.error("User {0} enrolled in non-existent course {1}"
.format(user.username, enrollment.course_id))
@@ -478,13 +478,13 @@ def dashboard(request):
# Global staff can see what courses errored on their dashboard
staff_access = False
errored_courses = {}
if has_access(user, 'global', 'staff'):
if has_access(user, 'staff', 'global'):
# Show any courses that errored on load
staff_access = True
errored_courses = modulestore().get_errored_courses()
show_courseware_links_for = frozenset(course.id for course, _enrollment in course_enrollment_pairs
if has_access(request.user, course, 'load'))
if has_access(request.user, 'load', course))
course_modes = {course.id: complete_course_mode_info(course.id, enrollment) for course, enrollment in course_enrollment_pairs}
cert_statuses = {course.id: cert_info(request.user, course) for course, _enrollment in course_enrollment_pairs}
@@ -617,10 +617,11 @@ def change_enrollment(request):
user = request.user
action = request.POST.get("enrollment_action")
course_id = request.POST.get("course_id")
if course_id is None:
if 'course_id' not in request.POST:
return HttpResponseBadRequest(_("Course id not specified"))
course_id = SlashSeparatedCourseKey.from_deprecated_string(request.POST.get("course_id"))
if not user.is_authenticated():
return HttpResponseForbidden()
@@ -634,7 +635,7 @@ def change_enrollment(request):
.format(user.username, course_id))
return HttpResponseBadRequest(_("Course id is invalid"))
if not has_access(user, course, 'enroll'):
if not has_access(user, 'enroll', course):
return HttpResponseBadRequest(_("Enrollment is closed"))
# see if we have already filled up all allowed enrollments
@@ -648,7 +649,7 @@ def change_enrollment(request):
available_modes = CourseMode.modes_for_course(course_id)
if len(available_modes) > 1:
return HttpResponse(
reverse("course_modes_choose", kwargs={'course_id': course_id})
reverse("course_modes_choose", kwargs={'course_id': course_id.to_deprecated_string()})
)
current_mode = available_modes[0]
@@ -664,7 +665,7 @@ def change_enrollment(request):
# the user to the shopping cart page always, where they can reasonably discern the status of their cart,
# whether things got added, etc
shoppingcart.views.add_course_to_cart(request, course_id)
shoppingcart.views.add_course_to_cart(request, course_id.to_deprecated_string())
return HttpResponse(
reverse("shoppingcart.views.show_cart")
)
@@ -686,7 +687,7 @@ def _parse_course_id_from_string(input_str):
"""
m_obj = re.match(r'^/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)', input_str)
if m_obj:
return m_obj.group('course_id')
return SlashSeparatedCourseKey.from_deprecated_string(m_obj.group('course_id'))
return None
@@ -696,12 +697,12 @@ def _get_course_enrollment_domain(course_id):
@param course_id:
@return:
"""
try:
course = course_from_id(course_id)
return course.enrollment_domain
except ItemNotFoundError:
course = course_from_id(course_id)
if course is None:
return None
return course.enrollment_domain
@ensure_csrf_cookie
def accounts_login(request):
@@ -1378,6 +1379,9 @@ def auto_auth(request):
full_name = request.GET.get('full_name', username)
is_staff = request.GET.get('staff', None)
course_id = request.GET.get('course_id', None)
course_key = None
if course_id:
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
role_names = [v.strip() for v in request.GET.get('roles', '').split(',') if v.strip()]
# Get or create the user object
@@ -1413,12 +1417,12 @@ def auto_auth(request):
reg.save()
# Enroll the user in a course
if course_id is not None:
CourseEnrollment.enroll(user, course_id)
if course_key is not None:
CourseEnrollment.enroll(user, course_key)
# Apply the roles
for role_name in role_names:
role = Role.objects.get(name=role_name, course_id=course_id)
role = Role.objects.get(name=role_name, course_id=course_key)
user.roles.add(role)
# Log in as the user
@@ -1865,15 +1869,16 @@ def change_email_settings(request):
user = request.user
course_id = request.POST.get("course_id")
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
receive_emails = request.POST.get("receive_emails")
if receive_emails:
optout_object = Optout.objects.filter(user=user, course_id=course_id)
optout_object = Optout.objects.filter(user=user, course_id=course_key)
if optout_object:
optout_object.delete()
log.info(u"User {0} ({1}) opted in to receive emails from course {2}".format(user.username, user.email, course_id))
track.views.server_track(request, "change-email-settings", {"receive_emails": "yes", "course": course_id}, page='dashboard')
else:
Optout.objects.get_or_create(user=user, course_id=course_id)
Optout.objects.get_or_create(user=user, course_id=course_key)
log.info(u"User {0} ({1}) opted out of receiving emails from course {2}".format(user.username, user.email, course_id))
track.views.server_track(request, "change-email-settings", {"receive_emails": "no", "course": course_id}, page='dashboard')
@@ -1889,7 +1894,7 @@ def token(request):
the token was issued. This will be stored with the user along with
the id for identification purposes in the backend.
'''
course_id = request.GET.get("course_id")
course_id = SlashSeparatedCourseKey.from_deprecated_string(request.GET.get("course_id"))
course = course_from_id(course_id)
dtnow = datetime.datetime.now()
dtutcnow = datetime.datetime.utcnow()