Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
7f4da141
Commit
7f4da141
authored
Sep 16, 2014
by
Adam Palay
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add middleware optionally to catch unenrolled students who fail has_access (TNL-286)
parent
6bf52074
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
117 additions
and
2 deletions
+117
-2
lms/djangoapps/courseware/courses.py
+13
-1
lms/djangoapps/courseware/middleware.py
+23
-0
lms/djangoapps/courseware/tests/test_middleware.py
+53
-0
lms/djangoapps/django_comment_client/forum/tests.py
+24
-0
lms/djangoapps/django_comment_client/forum/views.py
+1
-1
lms/envs/common.py
+3
-0
No files found.
lms/djangoapps/courseware/courses.py
View file @
7f4da141
...
...
@@ -20,6 +20,7 @@ from xmodule.x_module import STUDENT_VIEW
from
courseware.access
import
has_access
from
courseware.model_data
import
FieldDataCache
from
courseware.module_render
import
get_module
from
student.models
import
CourseEnrollment
import
branding
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -72,7 +73,13 @@ def get_course_by_id(course_key, depth=0):
raise
Http404
(
"Course not found."
)
def
get_course_with_access
(
user
,
action
,
course_key
,
depth
=
0
):
class
UserNotEnrolled
(
Http404
):
def
__init__
(
self
,
course_key
):
super
(
UserNotEnrolled
,
self
)
.
__init__
()
self
.
course_key
=
course_key
def
get_course_with_access
(
user
,
action
,
course_key
,
depth
=
0
,
check_if_enrolled
=
False
):
"""
Given a course_key, look up the corresponding course descriptor,
check that the user has the access to perform the specified action
...
...
@@ -86,6 +93,11 @@ def get_course_with_access(user, action, course_key, depth=0):
course
=
get_course_by_id
(
course_key
,
depth
=
depth
)
if
not
has_access
(
user
,
action
,
course
,
course_key
):
if
check_if_enrolled
and
not
CourseEnrollment
.
is_enrolled
(
user
,
course_key
):
# If user is not enrolled, raise UserNotEnrolled exception that will
# be caught by middleware
raise
UserNotEnrolled
(
course_key
)
# Deliberately return a non-specific error message to avoid
# leaking info about access control settings
raise
Http404
(
"Course not found."
)
...
...
lms/djangoapps/courseware/middleware.py
0 → 100644
View file @
7f4da141
"""
Middleware for the courseware app
"""
from
django.shortcuts
import
redirect
from
django.core.urlresolvers
import
reverse
from
courseware.courses
import
UserNotEnrolled
class
RedirectUnenrolledMiddleware
(
object
):
"""
Catch UserNotEnrolled errors thrown by `get_course_with_access` and redirect
users to the course about page
"""
def
process_exception
(
self
,
request
,
exception
):
if
isinstance
(
exception
,
UserNotEnrolled
):
course_key
=
exception
.
course_key
return
redirect
(
reverse
(
'courseware.views.course_about'
,
args
=
[
course_key
.
to_deprecated_string
()]
)
)
lms/djangoapps/courseware/tests/test_middleware.py
0 → 100644
View file @
7f4da141
"""
Tests for courseware middleware
"""
from
django.core.urlresolvers
import
reverse
from
django.test.utils
import
override_settings
from
django.test.client
import
RequestFactory
from
django.http
import
Http404
from
mock
import
patch
from
courseware.tests.modulestore_config
import
TEST_DATA_MIXED_MODULESTORE
import
courseware.courses
as
courses
from
courseware.middleware
import
RedirectUnenrolledMiddleware
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
@override_settings
(
MODULESTORE
=
TEST_DATA_MIXED_MODULESTORE
)
class
CoursewareMiddlewareTestCase
(
ModuleStoreTestCase
):
"""Tests that courseware middleware is correctly redirected"""
def
setUp
(
self
):
self
.
course
=
CourseFactory
.
create
()
def
check_user_not_enrolled_redirect
(
self
):
"""A UserNotEnrolled exception should trigger a redirect"""
request
=
RequestFactory
()
.
get
(
"dummy_url"
)
response
=
RedirectUnenrolledMiddleware
()
.
process_exception
(
request
,
courses
.
UserNotEnrolled
(
self
.
course
.
id
)
)
self
.
assertEqual
(
response
.
status_code
,
302
)
# make sure we redirect to the course about page
expected_url
=
reverse
(
"about_course"
,
args
=
[
self
.
course
.
id
.
to_deprecated_string
()]
)
target_url
=
response
.
_headers
[
'location'
][
1
]
self
.
assertTrue
(
target_url
.
endswith
(
expected_url
))
def
test_user_not_enrolled_redirect
(
self
):
self
.
check_user_not_enrolled_redirect
()
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
"ENABLE_MKTG_SITE"
:
True
})
def
test_user_not_enrolled_redirect_mktg
(
self
):
self
.
check_user_not_enrolled_redirect
()
def
test_process_404
(
self
):
"""A 404 should not trigger anything"""
request
=
RequestFactory
()
.
get
(
"dummy_url"
)
response
=
RedirectUnenrolledMiddleware
()
.
process_exception
(
request
,
Http404
()
)
self
.
assertIsNone
(
response
)
lms/djangoapps/django_comment_client/forum/tests.py
View file @
7f4da141
...
...
@@ -20,6 +20,7 @@ from django_comment_client.tests.utils import CohortedContentTestCase
from
django_comment_client.forum
import
views
from
courseware.tests.modulestore_config
import
TEST_DATA_MIXED_MODULESTORE
from
courseware.courses
import
UserNotEnrolled
from
nose.tools
import
assert_true
# pylint: disable=E0611
from
mock
import
patch
,
Mock
,
ANY
,
call
...
...
@@ -913,3 +914,26 @@ class FollowedThreadsUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin):
response_data
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response_data
[
"discussion_data"
][
0
][
"title"
],
text
)
self
.
assertEqual
(
response_data
[
"discussion_data"
][
0
][
"body"
],
text
)
@override_settings
(
MODULESTORE
=
TEST_DATA_MIXED_MODULESTORE
)
class
EnrollmentTestCase
(
ModuleStoreTestCase
):
"""
Tests for the behavior of views depending on if the student is enrolled
in the course
"""
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
"ENABLE_DISCUSSION_SERVICE"
:
True
})
def
setUp
(
self
):
super
(
EnrollmentTestCase
,
self
)
.
setUp
()
self
.
course
=
CourseFactory
.
create
()
self
.
student
=
UserFactory
.
create
()
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
"ENABLE_DISCUSSION_SERVICE"
:
True
})
@patch
(
'lms.lib.comment_client.utils.requests.request'
)
def
test_unenrolled
(
self
,
mock_request
):
mock_request
.
side_effect
=
make_mock_request_impl
(
'dummy'
)
request
=
RequestFactory
()
.
get
(
'dummy_url'
)
request
.
user
=
self
.
student
with
self
.
assertRaises
(
UserNotEnrolled
):
views
.
forum_form_discussion
(
request
,
course_id
=
self
.
course
.
id
.
to_deprecated_string
())
lms/djangoapps/django_comment_client/forum/views.py
View file @
7f4da141
...
...
@@ -163,7 +163,7 @@ def forum_form_discussion(request, course_id):
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
nr_transaction
=
newrelic
.
agent
.
current_transaction
()
course
=
get_course_with_access
(
request
.
user
,
'load_forum'
,
course_key
)
course
=
get_course_with_access
(
request
.
user
,
'load_forum'
,
course_key
,
check_if_enrolled
=
True
)
course_settings
=
make_course_settings
(
course
,
include_category_map
=
True
)
user
=
cc
.
User
.
from_django_user
(
request
.
user
)
...
...
lms/envs/common.py
View file @
7f4da141
...
...
@@ -941,6 +941,9 @@ MIDDLEWARE_CLASSES = (
# use Django built in clickjacking protection
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
# to redirected unenrolled students to the course info page
'courseware.middleware.RedirectUnenrolledMiddleware'
,
'course_wiki.middleware.WikiAccessMiddleware'
,
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment