urls.py 24.3 KB
Newer Older
Piotr Mitros committed
1
from django.conf import settings
2
from django.conf.urls import patterns, include, url
Diana Huang committed
3
from ratelimitbackend import admin
4
from django.conf.urls.static import static
5

6
import django.contrib.auth.views
Piotr Mitros committed
7 8

# Uncomment the next two lines to enable the admin:
9
if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
10
    admin.autodiscover()
Piotr Mitros committed
11

David Baumgold committed
12
urlpatterns = ('',  # nopep8
13 14
    # certificate view
    url(r'^update_certificate$', 'certificates.views.update_certificate'),
Calen Pennington committed
15
    url(r'^$', 'branding.views.index', name="root"),   # Main marketing page, or redirect to courseware
16
    url(r'^dashboard$', 'student.views.dashboard', name="dashboard"),
daniel cebrian committed
17
    url(r'^token$', 'student.views.token', name="token"),
18
    url(r'^login$', 'student.views.signin_user', name="signin_user"),
19
    url(r'^register$', 'student.views.register_user', name="register_user"),
20

21
    url(r'^admin_dashboard$', 'dashboard.views.dashboard'),
22

23
    url(r'^change_email$', 'student.views.change_email_request', name="change_email"),
24
    url(r'^email_confirm/(?P<key>[^/]*)$', 'student.views.confirm_email_change'),
25
    url(r'^change_name$', 'student.views.change_name_request', name="change_name"),
26 27 28
    url(r'^accept_name_change$', 'student.views.accept_name_change'),
    url(r'^reject_name_change$', 'student.views.reject_name_change'),
    url(r'^pending_name_changes$', 'student.views.pending_name_changes'),
29
    url(r'^event$', 'track.views.user_track'),
Calen Pennington committed
30
    url(r'^t/(?P<template>[^/]*)$', 'static_template_view.views.index'),   # TODO: Is this used anymore? What is STATIC_GRAB?
31

32
    url(r'^accounts/login$', 'student.views.accounts_login', name="accounts_login"),
33 34 35 36
    url(r'^accounts/manage_user_standing', 'student.views.manage_user_standing',
        name='manage_user_standing'),
    url(r'^accounts/disable_account_ajax$', 'student.views.disable_account_ajax',
        name="disable_account_ajax"),
37

38 39
    url(r'^login_ajax$', 'student.views.login_user', name="login"),
    url(r'^login_ajax/(?P<error>[^/]*)$', 'student.views.login_user'),
40
    url(r'^logout$', 'student.views.logout_user', name='logout'),
41
    url(r'^create_account$', 'student.views.create_account', name='create_account'),
42 43
    url(r'^activate/(?P<key>[^/]*)$', 'student.views.activate_account', name="activate"),

44
    url(r'^password_reset/$', 'student.views.password_reset', name='password_reset'),
45 46
    ## Obsolete Django views for password resets
    ## TODO: Replace with Mako-ized views
47 48 49 50 51
    url(r'^password_change/$', django.contrib.auth.views.password_change,
        name='auth_password_change'),
    url(r'^password_change_done/$', django.contrib.auth.views.password_change_done,
        name='auth_password_change_done'),
    url(r'^password_reset_confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
52
        'student.views.password_reset_confirm_wrapper',
Piotr Mitros committed
53
        name='auth_password_reset_confirm'),
54
    url(r'^password_reset_complete/$', django.contrib.auth.views.password_reset_complete,
Piotr Mitros committed
55
        name='auth_password_reset_complete'),
56
    url(r'^password_reset_done/$', django.contrib.auth.views.password_reset_done,
Piotr Mitros committed
57
        name='auth_password_reset_done'),
58

59
    url(r'^heartbeat$', include('heartbeat.urls')),
60 61

    url(r'^user_api/', include('user_api.urls')),
62

63 64
    url(r'^lang_pref/', include('lang_pref.urls')),

65
    url(r'^', include('waffle.urls')),
66 67

    url(r'^i18n/', include('django.conf.urls.i18n')),
68 69

    url(r'^embargo$', 'student.views.embargo', name="embargo"),
70
)
71

72
# if settings.FEATURES.get("MULTIPLE_ENROLLMENT_ROLES"):
73 74 75 76
urlpatterns += (
    url(r'^verify_student/', include('verify_student.urls')),
    url(r'^course_modes/', include('course_modes.urls')),
)
77 78


79 80
js_info_dict = {
    'domain': 'djangojs',
81 82
    # No packages needed, we get LOCALE_PATHS anyway.
    'packages': (),
83 84 85 86 87 88 89
}

urlpatterns += (
    # Serve catalog of localized strings to be rendered by Javascript
    url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
)

Carson Gee committed
90 91 92 93 94 95
# sysadmin dashboard, to see what courses are loaded, to delete & load courses
if settings.FEATURES["ENABLE_SYSADMIN_DASHBOARD"]:
    urlpatterns += (
        url(r'^sysadmin/', include('dashboard.sysadmin_urls')),
    )

96 97
#Semi-static views (these need to be rendered and have the login bar, but don't change)
urlpatterns += (
98
    url(r'^404$', 'static_template_view.views.render',
99
        {'template': '404.html'}, name="404"),
Piotr Mitros committed
100 101
)

102
# Semi-static views only used by edX, not by themes
103
if not settings.FEATURES["USE_CUSTOM_THEME"]:
104 105 106 107 108 109
    urlpatterns += (
        url(r'^jobs$', 'static_template_view.views.render',
            {'template': 'jobs.html'}, name="jobs"),
        url(r'^press$', 'student.views.press', name="press"),
        url(r'^media-kit$', 'static_template_view.views.render',
            {'template': 'media-kit.html'}, name="media-kit"),
110 111
        url(r'^faq$', 'static_template_view.views.render',
            {'template': 'faq.html'}, name="faq_edx"),
112 113 114 115 116 117 118
        url(r'^help$', 'static_template_view.views.render',
            {'template': 'help.html'}, name="help_edx"),

        # TODO: (bridger) The copyright has been removed until it is updated for edX
        # url(r'^copyright$', 'static_template_view.views.render',
        #     {'template': 'copyright.html'}, name="copyright"),

119
        # Press releases
120 121 122 123 124
        url(r'^press/([_a-zA-Z0-9-]+)$', 'static_template_view.views.render_press_release', name='press_release'),

        # Favicon
        (r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url': '/static/images/favicon.ico'}),

125
        url(r'^submit_feedback$', 'util.views.submit_feedback'),
126 127 128 129 130 131 132 133 134 135 136

    )

# Only enable URLs for those marketing links actually enabled in the
# settings. Disable URLs by marking them as None.
for key, value in settings.MKTG_URL_LINK_MAP.items():
    # Skip disabled URLs
    if value is None:
        continue

    # These urls are enabled separately
137
    if key == "ROOT" or key == "COURSES":
138 139 140 141 142 143 144 145
        continue

    # Make the assumptions that the templates are all in the same dir
    # and that they all match the name of the key (plus extension)
    template = "%s.html" % key.lower()

    # To allow theme templates to inherit from default templates,
    # prepend a standard prefix
146
    if settings.FEATURES["USE_CUSTOM_THEME"]:
147 148 149 150 151 152 153 154 155
        template = "theme-" + template

    # Make the assumption that the URL we want is the lowercased
    # version of the map key
    urlpatterns += (url(r'^%s' % key.lower(),
                        'static_template_view.views.render',
                        {'template': template}, name=value),)


156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
# Multicourse wiki (Note: wiki urls must be above the courseware ones because of
# the custom tab catch-all)
if settings.WIKI_ENABLED:
    from wiki.urls import get_pattern as wiki_pattern
    from django_notify.urls import get_pattern as notify_pattern

    urlpatterns += (
        # First we include views from course_wiki that we use to override the default views.
        # They come first in the urlpatterns so they get resolved first
        url('^wiki/create-root/$', 'course_wiki.views.root_create', name='root_create'),
        url(r'^wiki/', include(wiki_pattern())),
        url(r'^notify/', include(notify_pattern())),

        # These urls are for viewing the wiki in the context of a course. They should
        # never be returned by a reverse() so they come after the other url patterns
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/course_wiki/?$',
            'course_wiki.views.course_wiki_redirect', name="course_wiki"),
        url(r'^courses/(?:[^/]+/[^/]+/[^/]+)/wiki/', include(wiki_pattern())),
    )

176

Piotr Mitros committed
177
if settings.COURSEWARE_ENABLED:
178
    urlpatterns += (
179 180
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/jump_to/(?P<location>.*)$',
            'courseware.views.jump_to', name="jump_to"),
181 182
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/jump_to_id/(?P<module_id>.*)$',
            'courseware.views.jump_to_id', name="jump_to_id"),
183 184 185
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/xblock/(?P<usage_id>[^/]*)/handler/(?P<handler>[^/]*)(?:/(?P<suffix>.*))?$',
            'courseware.module_render.handle_xblock_callback',
            name='xblock_handler'),
186 187 188
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/xblock/(?P<usage_id>[^/]*)/handler_noauth/(?P<handler>[^/]*)(?:/(?P<suffix>.*))?$',
            'courseware.module_render.handle_xblock_callback_noauth',
            name='xblock_handler_noauth'),
189 190 191
        url(r'xblock/resource/(?P<block_type>[^/]+)/(?P<uri>.*)$',
            'courseware.module_render.xblock_resource',
            name='xblock_resource_url'),
192

193 194 195 196 197 198 199 200
        # Software Licenses

        # TODO: for now, this is the endpoint of an ajax replay
        # service that retrieve and assigns license numbers for
        # software assigned to a course. The numbers have to be loaded
        # into the database.
        url(r'^software-licenses$', 'licenses.views.user_software_license', name="user_software_license"),

201
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/xqueue/(?P<userid>[^/]*)/(?P<mod_id>.*?)/(?P<dispatch>[^/]*)$',
202 203
            'courseware.module_render.xqueue_callback',
            name='xqueue_callback'),
204 205
        url(r'^change_setting$', 'student.views.change_setting',
            name='change_setting'),
206

207
        # TODO: These views need to be updated before they work
208
        url(r'^calculate$', 'util.views.calculate'),
209 210 211
        # TODO: We should probably remove the circuit package. I believe it was only used in the old way of saving wiki circuits for the wiki
        # url(r'^edit_circuit/(?P<circuit>[^/]*)$', 'circuit.views.edit_circuit'),
        # url(r'^save_circuit/(?P<circuit>[^/]*)$', 'circuit.views.save_circuit'),
212

213
        url(r'^courses/?$', 'branding.views.courses', name="courses"),
214
        url(r'^change_enrollment$',
215
            'student.views.change_enrollment', name="change_enrollment"),
216
        url(r'^change_email_settings$', 'student.views.change_email_settings', name="change_email_settings"),
217

218
        #About the course
219
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/about$',
220
            'courseware.views.course_about', name="about_course"),
221
        #View for mktg site (kept for backwards compatibility TODO - remove before merge to master)
John Jarvis committed
222 223
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/mktg-about$',
            'courseware.views.mktg_course_about', name="mktg_about_course"),
224 225 226 227
        #View for mktg site
        url(r'^mktg/(?P<course_id>.*)$',
            'courseware.views.mktg_course_about', name="mktg_about_course"),

228
        #Inside the course
229 230
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/$',
            'courseware.views.course_info', name="course_root"),
231
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/info$',
232
            'courseware.views.course_info', name="info"),
233
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/syllabus$',
Calen Pennington committed
234
            'courseware.views.syllabus', name="syllabus"),   # TODO arjun remove when custom tabs in place, see courseware/courses.py
235

236
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/book/(?P<book_index>\d+)/$',
237
            'staticbook.views.index', name="book"),
238
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/book/(?P<book_index>\d+)/(?P<page>\d+)$',
239
            'staticbook.views.index', name="book"),
Brian Wilson committed
240

241
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/pdfbook/(?P<book_index>\d+)/$',
Brian Wilson committed
242
            'staticbook.views.pdf_index', name="pdf_book"),
243
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/pdfbook/(?P<book_index>\d+)/(?P<page>\d+)$',
244
            'staticbook.views.pdf_index', name="pdf_book"),
Brian Wilson committed
245

246
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/pdfbook/(?P<book_index>\d+)/chapter/(?P<chapter>\d+)/$',
247
            'staticbook.views.pdf_index', name="pdf_book"),
248
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/pdfbook/(?P<book_index>\d+)/chapter/(?P<chapter>\d+)/(?P<page>\d+)$',
249
            'staticbook.views.pdf_index', name="pdf_book"),
Brian Wilson committed
250

251
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/htmlbook/(?P<book_index>\d+)/$',
252
            'staticbook.views.html_index', name="html_book"),
253
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/htmlbook/(?P<book_index>\d+)/chapter/(?P<chapter>\d+)/$',
254
            'staticbook.views.html_index', name="html_book"),
255

256
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/courseware/?$',
257
            'courseware.views.index', name="courseware"),
258 259
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/courseware/(?P<chapter>[^/]*)/$',
            'courseware.views.index', name="courseware_chapter"),
260
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/courseware/(?P<chapter>[^/]*)/(?P<section>[^/]*)/$',
261
            'courseware.views.index', name="courseware_section"),
262 263
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/courseware/(?P<chapter>[^/]*)/(?P<section>[^/]*)/(?P<position>[^/]*)/?$',
            'courseware.views.index', name="courseware_position"),
Brian Wilson committed
264

265 266
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/progress$',
            'courseware.views.progress', name="progress"),
267
        # Takes optional student_id for instructor use--shows profile as that student sees it.
268 269
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/progress/(?P<student_id>[^/]*)/$',
            'courseware.views.progress', name="student_progress"),
270

271
        # For the instructor
272
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor$',
273
            'instructor.views.legacy.instructor_dashboard', name="instructor_dashboard"),
274

275
        # see ENABLE_INSTRUCTOR_BETA_DASHBOARD section for more urls
276

277
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/gradebook$',
278
            'instructor.views.legacy.gradebook', name='gradebook'),
279
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/grade_summary$',
280
            'instructor.views.legacy.grade_summary', name='grade_summary'),
281
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/staff_grading$',
282
            'open_ended_grading.views.staff_grading', name='staff_grading'),
283
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/staff_grading/get_next$',
284
            'open_ended_grading.staff_grading_service.get_next', name='staff_grading_get_next'),
285
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/staff_grading/save_grade$',
286
            'open_ended_grading.staff_grading_service.save_grade', name='staff_grading_save_grade'),
287
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/staff_grading/get_problem_list$',
288
            'open_ended_grading.staff_grading_service.get_problem_list', name='staff_grading_get_problem_list'),
289

290 291 292
        # Open Ended problem list
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/open_ended_problems$',
            'open_ended_grading.views.student_problem_list', name='open_ended_problems'),
293 294 295 296

        # Open Ended flagged problem list
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems$',
            'open_ended_grading.views.flagged_problem_list', name='open_ended_flagged_problems'),
297
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/open_ended_flagged_problems/take_action_on_flags$',
298
            'open_ended_grading.views.take_action_on_flags', name='open_ended_flagged_problems_take_action'),
Calen Pennington committed
299

300
        # Cohorts management
301 302 303 304 305 306 307 308 309 310 311
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/cohorts$',
            'course_groups.views.list_cohorts', name="cohorts"),
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/cohorts/add$',
            'course_groups.views.add_cohort',
            name="add_cohort"),
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/cohorts/(?P<cohort_id>[0-9]+)$',
            'course_groups.views.users_in_cohort',
            name="list_cohort"),
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/cohorts/(?P<cohort_id>[0-9]+)/add$',
            'course_groups.views.add_users_to_cohort',
            name="add_to_cohort"),
312 313 314
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/cohorts/(?P<cohort_id>[0-9]+)/delete$',
            'course_groups.views.remove_user_from_cohort',
            name="remove_from_cohort"),
315 316 317 318
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/cohorts/debug$',
            'course_groups.views.debug_cohort_mgmt',
            name="debug_cohort_mgmt"),

319 320 321
        # Open Ended Notifications
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/open_ended_notifications$',
            'open_ended_grading.views.combined_notifications', name='open_ended_notifications'),
322 323 324

        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/peer_grading$',
            'open_ended_grading.views.peer_grading', name='peer_grading'),
325 326 327 328

        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/notes$', 'notes.views.notes', name='notes'),
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/notes/', include('notes.urls')),

329
    )
330

331
    # allow course staff to change to student view of courseware
332
    if settings.FEATURES.get('ENABLE_MASQUERADE'):
333
        urlpatterns += (
334
            url(r'^masquerade/(?P<marg>.*)$', 'courseware.masquerade.handle_ajax', name="masquerade-switch"),
335 336
        )

337
    # discussion forums live within courseware, so courseware must be enabled first
338
    if settings.FEATURES.get('ENABLE_DISCUSSION_SERVICE'):
339 340
        urlpatterns += (
            url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/discussion/',
341 342 343
                include('django_comment_client.urls')),
            url(r'^notification_prefs/enable/', 'notification_prefs.views.ajax_enable'),
            url(r'^notification_prefs/disable/', 'notification_prefs.views.ajax_disable'),
344
            url(r'^notification_prefs/status/', 'notification_prefs.views.ajax_status'),
345 346
            url(r'^notification_prefs/unsubscribe/(?P<token>[a-zA-Z0-9-_=]+)/',
                'notification_prefs.views.set_subscription', {'subscribe': False}, name="unsubscribe_forum_update"),
347
            url(r'^notification_prefs/resubscribe/(?P<token>[a-zA-Z0-9-_=]+)/',
348
                'notification_prefs.views.set_subscription', {'subscribe': True}, name="resubscribe_forum_update"),
David Baumgold committed
349
        )
350 351
    urlpatterns += (
        # This MUST be the last view in the courseware--it's a catch-all for custom tabs.
352
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/(?P<tab_slug>[^/]+)/$',
353
        'courseware.views.static_tab', name="static_tab"),
David Baumgold committed
354
    )
355

356
    if settings.FEATURES.get('ENABLE_STUDENT_HISTORY_VIEW'):
357 358 359 360 361 362
        urlpatterns += (
            url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/submission_history/(?P<student_username>[^/]*)/(?P<location>.*?)$',
                'courseware.views.submission_history',
                name='submission_history'),
        )

363

364
if settings.COURSEWARE_ENABLED and settings.FEATURES.get('ENABLE_INSTRUCTOR_BETA_DASHBOARD'):
365 366 367 368
    urlpatterns += (
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor_dashboard$',
            'instructor.views.instructor_dashboard.instructor_dashboard_2', name="instructor_dashboard_2"),

369 370
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor_dashboard/api/',
            include('instructor.views.api_urls'))
371
    )
372

373 374 375 376 377 378 379 380 381 382 383
if settings.FEATURES.get('CLASS_DASHBOARD'):
    urlpatterns += (
        # Json request data for metrics for entire course
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/all_sequential_open_distrib$',
            'class_dashboard.views.all_sequential_open_distrib', name="all_sequential_open_distrib"),
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/all_problem_grade_distribution$',
            'class_dashboard.views.all_problem_grade_distribution', name="all_problem_grade_distribution"),

        # Json request data for metrics for particular section
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/problem_grade_distribution/(?P<section>\d+)$',
            'class_dashboard.views.section_problem_grade_distrib', name="section_problem_grade_distrib"),
384 385 386 387 388 389 390 391

        # For listing students that opened a sub-section
        url(r'^get_students_opened_subsection$',
            'class_dashboard.dashboard_data.get_students_opened_subsection', name="get_students_opened_subsection"),

        # For listing of students' grade per problem
        url(r'^get_students_problem_grades$',
            'class_dashboard.dashboard_data.get_students_problem_grades', name="get_students_problem_grades"),
392 393
    )

394
if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
395
    ## Jasmine and admin
396
    urlpatterns += (url(r'^admin/', include(admin.site.urls)),)
397

398
if settings.FEATURES.get('AUTH_USE_OPENID'):
ichuang committed
399 400
    urlpatterns += (
        url(r'^openid/login/$', 'django_openid_auth.views.login_begin', name='openid-login'),
401
        url(r'^openid/complete/$', 'external_auth.views.openid_login_complete', name='openid-complete'),
ichuang committed
402
        url(r'^openid/logo.gif$', 'django_openid_auth.views.logo', name='openid-logo'),
403 404
    )

405
if settings.FEATURES.get('AUTH_USE_SHIB'):
406 407 408 409
    urlpatterns += (
        url(r'^shib-login/$', 'external_auth.views.shib_login', name='shib-login'),
    )

410
if settings.FEATURES.get('AUTH_USE_CAS'):
411 412 413 414 415
    urlpatterns += (
        url(r'^cas-auth/login/$', 'external_auth.views.cas_login', name="cas-login"),
        url(r'^cas-auth/logout/$', 'django_cas.views.logout', {'next_page': '/'}, name="cas-logout"),
    )

416
if settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD'):
417 418 419 420 421 422 423 424
    urlpatterns += (
        url(r'^course_specific_login/(?P<course_id>[^/]+/[^/]+/[^/]+)/$',
            'external_auth.views.course_specific_login', name='course-specific-login'),
        url(r'^course_specific_register/(?P<course_id>[^/]+/[^/]+/[^/]+)/$',
            'external_auth.views.course_specific_register', name='course-specific-register'),

    )

425 426
# Shopping cart
urlpatterns += (
427
    url(r'^shoppingcart/', include('shoppingcart.urls')),
428 429
)

430

431
if settings.FEATURES.get('AUTH_USE_OPENID_PROVIDER'):
432
    urlpatterns += (
433
        url(r'^openid/provider/login/$', 'external_auth.views.provider_login', name='openid-provider-login'),
434
        url(r'^openid/provider/login/(?:.+)$', 'external_auth.views.provider_identity', name='openid-provider-login-identity'),
435 436
        url(r'^openid/provider/identity/$', 'external_auth.views.provider_identity', name='openid-provider-identity'),
        url(r'^openid/provider/xrds/$', 'external_auth.views.provider_xrds', name='openid-provider-xrds')
437
    )
ichuang committed
438

439
if settings.FEATURES.get('ENABLE_LMS_MIGRATION'):
440 441 442
    urlpatterns += (
        url(r'^migrate/modules$', 'lms_migration.migrate.manage_modulestores'),
        url(r'^migrate/reload/(?P<reload_dir>[^/]+)$', 'lms_migration.migrate.manage_modulestores'),
443
        url(r'^migrate/reload/(?P<reload_dir>[^/]+)/(?P<commit_id>[^/]+)$', 'lms_migration.migrate.manage_modulestores'),
444 445
        url(r'^gitreload$', 'lms_migration.migrate.gitreload'),
        url(r'^gitreload/(?P<reload_dir>[^/]+)$', 'lms_migration.migrate.gitreload'),
David Baumgold committed
446
    )
447

448
if settings.FEATURES.get('ENABLE_SQL_TRACKING_LOGS'):
449 450
    urlpatterns += (
        url(r'^event_logs$', 'track.views.view_tracking_log'),
451
        url(r'^event_logs/(?P<args>.+)$', 'track.views.view_tracking_log'),
David Baumgold committed
452
    )
453

454
if settings.FEATURES.get('ENABLE_SERVICE_STATUS'):
455 456 457 458
    urlpatterns += (
        url(r'^status/', include('service_status.urls')),
    )

459
if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
460 461 462 463
    urlpatterns += (
        url(r'^instructor_task_status/$', 'instructor_task.views.instructor_task_status', name='instructor_task_status'),
    )

464
if settings.FEATURES.get('RUN_AS_ANALYTICS_SERVER_ENABLED'):
465
    urlpatterns += (
Juho Kim committed
466
        url(r'^edinsights_service/', include('edinsights.core.urls')),
467
    )
468
    import edinsights.core.registry
469

Victor Shnayder committed
470 471 472 473 474 475
# FoldIt views
urlpatterns += (
    # The path is hardcoded into their app...
    url(r'^comm/foldit_ops', 'foldit.views.foldit_ops', name="foldit_ops"),
)

476
if settings.FEATURES.get('ENABLE_DEBUG_RUN_PYTHON'):
477 478 479
    urlpatterns += (
        url(r'^debug/run_python', 'debug.views.run_python'),
    )
480

481
# Crowdsourced hinting instructor manager.
482
if settings.FEATURES.get('ENABLE_HINTER_INSTRUCTOR_VIEW'):
483 484 485 486 487
    urlpatterns += (
        url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/hint_manager$',
            'instructor.hint_manager.hint_manager', name="hint_manager"),
    )

488
# enable automatic login
489
if settings.FEATURES.get('AUTOMATIC_AUTH_FOR_TESTING'):
490
    urlpatterns += (
491
        url(r'^auto_auth$', 'student.views.auto_auth'),
492 493
    )

494 495 496 497 498 499
# Third-party auth.
if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH'):
    urlpatterns += (
        url(r'', include('third_party_auth.urls')),
    )

500 501
urlpatterns = patterns(*urlpatterns)

502
if settings.DEBUG:
503
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
504 505

#Custom error pages
506 507
handler404 = 'static_template_view.views.render_404'
handler500 = 'static_template_view.views.render_500'
508 509 510 511 512 513

# display error page templates, for testing purposes
urlpatterns += (
    url(r'404', handler404),
    url(r'500', handler500),
)