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
3be8f92b
Commit
3be8f92b
authored
Apr 01, 2017
by
Andy Armstrong
Committed by
GitHub
Apr 01, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14790 from edx/andya/course-redirects
Add data sharing consent redirect for more course tabs
parents
c6f2db35
0325425c
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
82 additions
and
97 deletions
+82
-97
common/djangoapps/course_modes/tests/test_views.py
+1
-1
common/djangoapps/course_modes/views.py
+1
-2
common/djangoapps/enrollment/tests/test_views.py
+1
-1
common/djangoapps/enrollment/views.py
+1
-1
common/djangoapps/student/views.py
+1
-1
common/djangoapps/third_party_auth/settings.py
+1
-1
common/djangoapps/third_party_auth/tests/test_settings.py
+2
-1
lms/djangoapps/course_wiki/middleware.py
+1
-1
lms/djangoapps/course_wiki/tests/tests.py
+1
-1
lms/djangoapps/course_wiki/views.py
+1
-1
lms/djangoapps/courseware/tests/test_course_info.py
+1
-1
lms/djangoapps/courseware/tests/test_view_authentication.py
+1
-1
lms/djangoapps/courseware/tests/test_views.py
+7
-9
lms/djangoapps/courseware/views/index.py
+2
-18
lms/djangoapps/courseware/views/views.py
+4
-14
lms/djangoapps/discussion/tests/test_views.py
+6
-10
lms/djangoapps/discussion/views.py
+0
-4
lms/djangoapps/student_account/views.py
+1
-1
lms/envs/common.py
+1
-0
lms/templates/navigation.html
+1
-1
lms/urls.py
+2
-2
openedx/features/enterprise_support/README.rst
+7
-0
openedx/features/enterprise_support/__init__.py
+0
-0
openedx/features/enterprise_support/api.py
+14
-7
openedx/features/enterprise_support/templates/enterprise_support/enterprise_consent_declined_notification.html
+3
-0
openedx/features/enterprise_support/tests/__init__.py
+0
-0
openedx/features/enterprise_support/tests/mixins/__init__.py
+0
-0
openedx/features/enterprise_support/tests/mixins/enterprise.py
+2
-2
openedx/features/enterprise_support/tests/test_api.py
+19
-16
No files found.
common/djangoapps/course_modes/tests/test_views.py
View file @
3be8f92b
...
...
@@ -22,11 +22,11 @@ from xmodule.modulestore.tests.factories import CourseFactory
from
course_modes.models
import
CourseMode
,
Mode
from
course_modes.tests.factories
import
CourseModeFactory
from
openedx.core.djangoapps.embargo.test_utils
import
restrict_course
from
openedx.features.enterprise_support.tests.mixins.enterprise
import
EnterpriseServiceMockMixin
from
student.models
import
CourseEnrollment
from
student.tests.factories
import
CourseEnrollmentFactory
,
UserFactory
from
util.testing
import
UrlResetMixin
from
openedx.core.djangoapps.theming.tests.test_util
import
with_comprehensive_theme
from
util.tests.mixins.enterprise
import
EnterpriseServiceMockMixin
from
util.tests.mixins.discovery
import
CourseCatalogServiceMockMixin
from
util
import
organizations_helpers
as
organizations_api
...
...
common/djangoapps/course_modes/views.py
View file @
3be8f92b
...
...
@@ -20,14 +20,13 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
from
xmodule.modulestore.django
import
modulestore
from
lms.djangoapps.commerce.utils
import
EcommerceService
from
openedx.core.djangoapps.api_admin.utils
import
course_discovery_api_client
from
course_modes.models
import
CourseMode
from
courseware.access
import
has_access
from
edxmako.shortcuts
import
render_to_response
from
openedx.core.djangoapps.embargo
import
api
as
embargo_api
from
openedx.features.enterprise_support
import
api
as
enterprise_api
from
student.models
import
CourseEnrollment
from
util.db
import
outer_atomic
from
util
import
enterprise_helpers
as
enterprise_api
from
util
import
organizations_helpers
as
organization_api
...
...
common/djangoapps/enrollment/tests/test_views.py
View file @
3be8f92b
...
...
@@ -26,7 +26,7 @@ from course_modes.models import CourseMode
from
enrollment.views
import
EnrollmentUserThrottle
from
util.models
import
RateLimitConfiguration
from
util.testing
import
UrlResetMixin
from
util
.tests.mixins.enterprise
import
EnterpriseServiceMockMixin
from
openedx.features.enterprise_support
.tests.mixins.enterprise
import
EnterpriseServiceMockMixin
from
enrollment
import
api
from
enrollment.errors
import
CourseEnrollmentError
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
...
...
common/djangoapps/enrollment/views.py
View file @
3be8f92b
...
...
@@ -20,13 +20,13 @@ from openedx.core.djangoapps.cors_csrf.authentication import SessionAuthenticati
from
openedx.core.djangoapps.cors_csrf.decorators
import
ensure_csrf_cookie_cross_domain
from
openedx.core.djangoapps.embargo
import
api
as
embargo_api
from
openedx.core.djangoapps.user_api.preferences.api
import
update_email_opt_in
from
openedx.features.enterprise_support.api
import
enterprise_enabled
,
EnterpriseApiClient
,
EnterpriseApiException
from
openedx.core.lib.api.authentication
import
(
SessionAuthenticationAllowInactiveUser
,
OAuth2AuthenticationAllowInactiveUser
,
)
from
openedx.core.lib.api.permissions
import
ApiKeyHeaderPermission
,
ApiKeyHeaderPermissionIsAuthenticated
from
openedx.core.lib.exceptions
import
CourseNotFoundError
from
openedx.core.lib.log_utils
import
audit_log
from
util.enterprise_helpers
import
enterprise_enabled
,
EnterpriseApiClient
,
EnterpriseApiException
from
enrollment
import
api
from
enrollment.errors
import
(
CourseEnrollmentError
,
...
...
common/djangoapps/student/views.py
View file @
3be8f92b
...
...
@@ -103,7 +103,6 @@ from util.milestones_helpers import (
)
from
util.password_policy_validators
import
validate_password_strength
from
util.enterprise_helpers
import
get_dashboard_consent_notification
import
third_party_auth
from
third_party_auth
import
pipeline
,
provider
from
student.helpers
import
(
...
...
@@ -117,6 +116,7 @@ from student.models import anonymous_id_for_user, UserAttribute, EnrollStatusCha
from
shoppingcart.models
import
DonationConfiguration
,
CourseRegistrationCode
from
openedx.core.djangoapps.embargo
import
api
as
embargo_api
from
openedx.features.enterprise_support.api
import
get_dashboard_consent_notification
import
analytics
from
eventtracking
import
tracker
...
...
common/djangoapps/third_party_auth/settings.py
View file @
3be8f92b
...
...
@@ -10,7 +10,7 @@ If true, it:
b) calls apply_settings(), passing in the Django settings
"""
from
util.enterprise_helpers
import
insert_enterprise_pipeline_elements
from
openedx.features.enterprise_support.api
import
insert_enterprise_pipeline_elements
_FIELDS_STORED_IN_SESSION
=
[
'auth_entry'
,
'next'
]
_MIDDLEWARE_CLASSES
=
(
...
...
common/djangoapps/third_party_auth/tests/test_settings.py
View file @
3be8f92b
...
...
@@ -2,9 +2,10 @@
from
third_party_auth
import
provider
,
settings
from
third_party_auth.tests
import
testutil
from
util.enterprise_helpers
import
enterprise_enabled
import
unittest
from
openedx.features.enterprise_support.api
import
enterprise_enabled
_ORIGINAL_AUTHENTICATION_BACKENDS
=
(
'first_authentication_backend'
,)
_ORIGINAL_INSTALLED_APPS
=
(
'first_installed_app'
,)
...
...
lms/djangoapps/course_wiki/middleware.py
View file @
3be8f92b
...
...
@@ -10,7 +10,7 @@ from courseware.courses import get_course_with_access, get_course_overview_with_
from
courseware.access
import
has_access
from
student.models
import
CourseEnrollment
from
util.request
import
course_id_from_url
from
util.enterprise_helpers
import
get_enterprise_consent_url
from
openedx.features.enterprise_support.api
import
get_enterprise_consent_url
class
WikiAccessMiddleware
(
object
):
...
...
lms/djangoapps/course_wiki/tests/tests.py
View file @
3be8f92b
...
...
@@ -2,7 +2,7 @@ from django.core.urlresolvers import reverse
from
nose.plugins.attrib
import
attr
from
courseware.tests.tests
import
LoginEnrollmentTestCase
from
util
.tests.mixins.enterprise
import
EnterpriseTestConsentRequired
from
openedx.features.enterprise_support
.tests.mixins.enterprise
import
EnterpriseTestConsentRequired
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
...
...
lms/djangoapps/course_wiki/views.py
View file @
3be8f92b
...
...
@@ -16,7 +16,7 @@ from courseware.courses import get_course_by_id
from
course_wiki.utils
import
course_wiki_slug
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
util.enterprise_helpers
import
data_sharing_consent_required
from
openedx.features.enterprise_support.api
import
data_sharing_consent_required
log
=
logging
.
getLogger
(
__name__
)
...
...
lms/djangoapps/courseware/tests/test_course_info.py
View file @
3be8f92b
...
...
@@ -60,7 +60,7 @@ class CourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
resp
=
self
.
client
.
get
(
url
)
self
.
assertNotIn
(
"You are not currently enrolled in this course"
,
resp
.
content
)
@mock.patch
(
'
courseware.views.views
.get_enterprise_consent_url'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.get_enterprise_consent_url'
)
def
test_redirection_missing_enterprise_consent
(
self
,
mock_get_url
):
"""
Verify that users viewing the course info who are enrolled, but have not provided
...
...
lms/djangoapps/courseware/tests/test_view_authentication.py
View file @
3be8f92b
...
...
@@ -197,7 +197,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
)
)
@patch
(
'
courseware.views.index
.get_enterprise_consent_url'
)
@patch
(
'
openedx.features.enterprise_support.api
.get_enterprise_consent_url'
)
def
test_redirection_missing_enterprise_consent
(
self
,
mock_get_url
):
"""
Verify that enrolled students are redirected to the Enterprise consent
...
...
lms/djangoapps/courseware/tests/test_views.py
View file @
3be8f92b
...
...
@@ -41,21 +41,25 @@ from commerce.models import CommerceConfiguration
from
course_modes.models
import
CourseMode
from
course_modes.tests.factories
import
CourseModeFactory
from
courseware.model_data
import
set_score
from
courseware.module_render
import
toc_for_course
from
courseware.testutils
import
RenderXBlockTestMixin
from
courseware.tests.factories
import
StudentModuleFactory
,
GlobalStaffFactory
from
courseware.url_helpers
import
get_redirect_url
from
courseware.user_state_client
import
DjangoXBlockUserStateClient
from
courseware.views.index
import
render_accordion
from
lms.djangoapps.commerce.utils
import
EcommerceService
# pylint: disable=import-error
from
milestones.tests.utils
import
MilestonesTestCaseMixin
from
openedx.core.djangoapps.catalog.tests.factories
import
CourseFactory
as
CatalogCourseFactory
from
openedx.core.djangoapps.catalog.tests.factories
import
ProgramFactory
,
CourseRunFactory
from
openedx.core.djangoapps.catalog.tests.mixins
import
CatalogIntegrationMixin
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
openedx.core.djangoapps.crawlers.models
import
CrawlersConfig
from
openedx.core.djangoapps.credit.api
import
set_credit_requirements
from
openedx.core.djangoapps.credit.models
import
CreditCourse
,
CreditProvider
from
openedx.core.djangoapps.programs.tests.mixins
import
ProgramsApiConfigMixin
from
openedx.core.djangoapps.self_paced.models
import
SelfPacedConfiguration
from
openedx.core.lib.gating
import
api
as
gating_api
from
openedx.features.enterprise_support.tests.mixins.enterprise
import
EnterpriseTestConsentRequired
from
student.models
import
CourseEnrollment
from
student.tests.factories
import
AdminFactory
,
UserFactory
,
CourseEnrollmentFactory
from
util.tests.mixins.enterprise
import
EnterpriseTestConsentRequired
from
util.tests.test_date_utils
import
fake_ugettext
,
fake_pgettext
from
util.url
import
reload_django_url_config
from
util.views
import
ensure_valid_course_key
...
...
@@ -64,12 +68,6 @@ from xmodule.modulestore.django import modulestore
from
xmodule.modulestore.tests.django_utils
import
TEST_DATA_MIXED_MODULESTORE
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
,
SharedModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
,
check_mongo_calls
from
openedx.core.djangoapps.catalog.tests.factories
import
CourseFactory
as
CatalogCourseFactory
from
openedx.core.djangoapps.catalog.tests.factories
import
ProgramFactory
,
CourseRunFactory
from
openedx.core.djangoapps.catalog.tests.mixins
import
CatalogIntegrationMixin
from
openedx.core.djangoapps.credit.api
import
set_credit_requirements
from
openedx.core.djangoapps.credit.models
import
CreditCourse
,
CreditProvider
from
openedx.core.djangoapps.programs.tests.mixins
import
ProgramsApiConfigMixin
@attr
(
shard
=
1
)
...
...
lms/djangoapps/courseware/views/index.py
View file @
3be8f92b
...
...
@@ -32,13 +32,12 @@ from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from
openedx.core.djangoapps.user_api.preferences.api
import
get_user_preference
from
openedx.core.djangoapps.crawlers.models
import
CrawlersConfig
from
openedx.core.djangoapps.monitoring_utils
import
set_custom_metrics_for_course_key
from
openedx.features.enterprise_support.api
import
data_sharing_consent_required
from
request_cache.middleware
import
RequestCache
from
shoppingcart.models
import
CourseRegistrationCode
from
student.models
import
CourseEnrollment
from
student.views
import
is_course_blocked
from
student.roles
import
GlobalStaff
from
survey.utils
import
must_answer_survey
from
util.enterprise_helpers
import
get_enterprise_consent_url
from
util.views
import
ensure_valid_course_key
from
xmodule.modulestore.django
import
modulestore
from
xmodule.x_module
import
STUDENT_VIEW
...
...
@@ -73,6 +72,7 @@ class CoursewareIndex(View):
@method_decorator
(
ensure_csrf_cookie
)
@method_decorator
(
cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
))
@method_decorator
(
ensure_valid_course_key
)
@method_decorator
(
data_sharing_consent_required
)
def
get
(
self
,
request
,
course_id
,
chapter
=
None
,
section
=
None
,
position
=
None
):
"""
Displays courseware accordion and associated content. If course, chapter,
...
...
@@ -194,22 +194,6 @@ class CoursewareIndex(View):
self
.
_redirect_if_needed_to_register
()
self
.
_redirect_if_needed_for_prereqs
()
self
.
_redirect_if_needed_for_course_survey
()
self
.
_redirect_if_data_sharing_consent_needed
()
def
_redirect_if_data_sharing_consent_needed
(
self
):
"""
Determine if the user needs to provide data sharing consent before accessing
the course, and redirect the user to provide consent if needed.
"""
course_id
=
unicode
(
self
.
course_key
)
consent_url
=
get_enterprise_consent_url
(
self
.
request
,
course_id
,
user
=
self
.
real_user
,
return_to
=
'courseware'
)
if
consent_url
:
log
.
warning
(
u'User
%
s cannot access the course
%
s because they have not granted consent'
,
self
.
real_user
,
course_id
,
)
raise
Redirect
(
consent_url
)
def
_redirect_if_needed_to_pay_for_course
(
self
):
"""
...
...
lms/djangoapps/courseware/views/views.py
View file @
3be8f92b
...
...
@@ -89,13 +89,13 @@ from openedx.core.djangoapps.programs.utils import ProgramMarketingDataExtender
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
openedx.core.djangoapps.self_paced.models
import
SelfPacedConfiguration
from
openedx.core.djangoapps.monitoring_utils
import
set_custom_metrics_for_course_key
from
openedx.features.enterprise_support.api
import
data_sharing_consent_required
from
shoppingcart.utils
import
is_shopping_cart_enabled
from
student.models
import
UserTestGroup
,
CourseEnrollment
from
student.roles
import
GlobalStaff
from
util.cache
import
cache
,
cache_if_anonymous
from
util.date_utils
import
strftime_localized
from
util.db
import
outer_atomic
from
util.enterprise_helpers
import
get_enterprise_consent_url
from
util.milestones_helpers
import
get_prerequisite_courses_display
from
util.views
import
_record_feedback_in_zendesk
from
util.views
import
ensure_valid_course_key
,
ensure_valid_usage_key
...
...
@@ -107,7 +107,6 @@ from ..entrance_exams import user_can_skip_entrance_exam
from
..module_render
import
get_module_for_descriptor
,
get_module
,
get_module_by_usage_id
from
web_fragments.fragment
import
Fragment
from
web_fragments.views
import
FragmentView
log
=
logging
.
getLogger
(
"edx.courseware"
)
...
...
@@ -291,6 +290,7 @@ def jump_to(_request, course_id, location):
@ensure_csrf_cookie
@ensure_valid_course_key
@data_sharing_consent_required
def
course_info
(
request
,
course_id
):
"""
Display the course's info.html, or 404 if there is no such course.
...
...
@@ -330,12 +330,6 @@ def course_info(request, course_id):
# to access CCX redirect him to dashboard.
return
redirect
(
reverse
(
'dashboard'
))
# If the user is sponsored by an enterprise customer, and we still need to get data
# sharing consent, redirect to do that first.
consent_url
=
get_enterprise_consent_url
(
request
,
course_id
,
user
=
user
,
return_to
=
'info'
)
if
consent_url
:
return
redirect
(
consent_url
)
# If the user needs to take an entrance exam to access this course, then we'll need
# to send them to that specific course module before allowing them into other areas
if
not
user_can_skip_entrance_exam
(
user
,
course
):
...
...
@@ -495,6 +489,7 @@ class CourseTabView(EdxFragmentView):
"""
@method_decorator
(
ensure_csrf_cookie
)
@method_decorator
(
ensure_valid_course_key
)
@method_decorator
(
data_sharing_consent_required
)
def
get
(
self
,
request
,
course_id
,
tab_type
,
**
kwargs
):
"""
Displays a course tab page that contains a web fragment.
...
...
@@ -811,6 +806,7 @@ def program_marketing(request, program_uuid):
@login_required
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@ensure_valid_course_key
@data_sharing_consent_required
def
progress
(
request
,
course_id
,
student_id
=
None
):
""" Display the progress page. """
course_key
=
CourseKey
.
from_string
(
course_id
)
...
...
@@ -838,12 +834,6 @@ def _progress(request, course_key, student_id):
course
=
get_course_with_access
(
request
.
user
,
'load'
,
course_key
,
depth
=
None
,
check_if_enrolled
=
True
)
prep_course_for_grading
(
course
,
request
)
# If the user is sponsored by an enterprise customer, and we still need to get data
# sharing consent, redirect to do that first.
consent_url
=
get_enterprise_consent_url
(
request
,
unicode
(
course
.
id
),
return_to
=
'progress'
)
if
consent_url
:
return
redirect
(
consent_url
)
# check to see if there is a required survey that must be taken before
# the user can access the course.
if
survey
.
utils
.
must_answer_survey
(
course
,
request
.
user
):
...
...
lms/djangoapps/discussion/tests/test_views.py
View file @
3be8f92b
...
...
@@ -23,8 +23,8 @@ from django_comment_client.utils import strip_none
from
lms.djangoapps.discussion
import
views
from
student.tests.factories
import
UserFactory
,
CourseEnrollmentFactory
from
util.testing
import
UrlResetMixin
from
util.tests.mixins.enterprise
import
EnterpriseTestConsentRequired
from
openedx.core.djangoapps.util.testing
import
ContentGroupTestCase
from
openedx.features.enterprise_support.tests.mixins.enterprise
import
EnterpriseTestConsentRequired
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.tests.django_utils
import
(
...
...
@@ -363,14 +363,12 @@ class SingleThreadQueryCountTestCase(ForumsEnableMixin, ModuleStoreTestCase):
(
ModuleStoreEnum
.
Type
.
split
,
False
,
1
,
3
,
3
,
12
,
1
),
(
ModuleStoreEnum
.
Type
.
split
,
False
,
50
,
3
,
3
,
12
,
1
),
# Enabling Enterprise integration increases the number of (cached and uncached) SQL queries by 1,
# because the presence of the user's consent for the course must be checked.
# But there should be no effect on the number of mongo queries made.
(
ModuleStoreEnum
.
Type
.
mongo
,
True
,
1
,
5
,
3
,
14
,
2
),
(
ModuleStoreEnum
.
Type
.
mongo
,
True
,
50
,
5
,
3
,
14
,
2
),
# Enabling Enterprise integration should have no effect on the number of mongo queries made.
(
ModuleStoreEnum
.
Type
.
mongo
,
True
,
1
,
5
,
3
,
13
,
1
),
(
ModuleStoreEnum
.
Type
.
mongo
,
True
,
50
,
5
,
3
,
13
,
1
),
# split mongo: 3 queries, regardless of thread response size.
(
ModuleStoreEnum
.
Type
.
split
,
True
,
1
,
3
,
3
,
1
3
,
2
),
(
ModuleStoreEnum
.
Type
.
split
,
True
,
50
,
3
,
3
,
1
3
,
2
),
(
ModuleStoreEnum
.
Type
.
split
,
True
,
1
,
3
,
3
,
1
2
,
1
),
(
ModuleStoreEnum
.
Type
.
split
,
True
,
50
,
3
,
3
,
1
2
,
1
),
)
@ddt.unpack
def
test_number_of_mongo_queries
(
...
...
@@ -1616,8 +1614,6 @@ class EnterpriseConsentTestCase(EnterpriseTestConsentRequired, ForumsEnableMixin
for
url
in
(
reverse
(
'discussion.views.forum_form_discussion'
,
kwargs
=
dict
(
course_id
=
course_id
)),
reverse
(
'discussion.views.inline_discussion'
,
kwargs
=
dict
(
course_id
=
course_id
,
discussion_id
=
self
.
discussion_id
)),
reverse
(
'discussion.views.single_thread'
,
kwargs
=
dict
(
course_id
=
course_id
,
discussion_id
=
self
.
discussion_id
,
thread_id
=
thread_id
)),
):
...
...
lms/djangoapps/discussion/views.py
View file @
3be8f92b
...
...
@@ -53,7 +53,6 @@ from django_comment_client.utils import (
)
import
django_comment_client.utils
as
utils
import
lms.lib.comment_client
as
cc
from
util.enterprise_helpers
import
data_sharing_consent_required
from
opaque_keys.edx.keys
import
CourseKey
...
...
@@ -199,7 +198,6 @@ def use_bulk_ops(view_func):
@login_required
@data_sharing_consent_required
@use_bulk_ops
def
inline_discussion
(
request
,
course_key
,
discussion_id
):
"""
...
...
@@ -236,7 +234,6 @@ def inline_discussion(request, course_key, discussion_id):
@login_required
@data_sharing_consent_required
@use_bulk_ops
def
forum_form_discussion
(
request
,
course_key
):
"""
...
...
@@ -277,7 +274,6 @@ def forum_form_discussion(request, course_key):
@require_GET
@login_required
@data_sharing_consent_required
@use_bulk_ops
def
single_thread
(
request
,
course_key
,
discussion_id
,
thread_id
):
"""
...
...
lms/djangoapps/student_account/views.py
View file @
3be8f92b
...
...
@@ -34,6 +34,7 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_
from
openedx.core.djangoapps.theming.helpers
import
is_request_in_themed_site
from
openedx.core.djangoapps.user_api.accounts.api
import
request_password_change
from
openedx.core.djangoapps.user_api.errors
import
UserNotFound
from
openedx.features.enterprise_support.api
import
set_enterprise_branding_filter_param
from
openedx.core.lib.time_zone_utils
import
TIME_ZONE_CHOICES
from
openedx.core.lib.edx_api_utils
import
get_edx_api_data
from
student.models
import
UserProfile
...
...
@@ -47,7 +48,6 @@ from third_party_auth import pipeline
from
third_party_auth.decorators
import
xframe_allow_whitelisted
from
util.bad_request_rate_limiter
import
BadRequestRateLimiter
from
util.date_utils
import
strftime_localized
from
util.enterprise_helpers
import
set_enterprise_branding_filter_param
AUDIT_LOG
=
logging
.
getLogger
(
"audit"
)
log
=
logging
.
getLogger
(
__name__
)
...
...
lms/envs/common.py
View file @
3be8f92b
...
...
@@ -2180,6 +2180,7 @@ INSTALLED_APPS = (
# Features
'openedx.features.course_bookmarks'
,
'openedx.features.course_experience'
,
'openedx.features.enterprise_support'
,
)
######################### CSRF #########################################
...
...
lms/templates/navigation.html
View file @
3be8f92b
...
...
@@ -14,7 +14,7 @@ from openedx.core.djangolib.markup import HTML, Text
from
branding
import
api
as
branding_api
#
app
that
handles
site
status
messages
from
status
.
status
import
get_site_status_msg
from
util
.
enterprise_helpers
import
get_enterprise_customer_logo_url
from
openedx
.
features
.
enterprise_support
.
api
import
get_enterprise_customer_logo_url
%
>
## Provide a hook for themes to inject branding on top.
...
...
lms/urls.py
View file @
3be8f92b
...
...
@@ -11,13 +11,13 @@ from django.conf.urls.static import static
from
courseware.views.views
import
CourseTabView
,
EnrollStaffView
,
StaticCourseTabView
from
config_models.views
import
ConfigurationModelCurrentAPIView
from
courseware.views.index
import
CoursewareIndex
from
django_comment_common.models
import
ForumsConfig
from
openedx.core.djangoapps.auth_exchange.views
import
LoginWithAccessTokenView
from
openedx.core.djangoapps.catalog.models
import
CatalogIntegration
from
openedx.core.djangoapps.programs.models
import
ProgramsApiConfig
from
openedx.core.djangoapps.self_paced.models
import
SelfPacedConfiguration
from
django_comment_common.models
import
ForumsConfig
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
util.enterprise_helpers
import
enterprise_enabled
from
openedx.features.enterprise_support.api
import
enterprise_enabled
# Uncomment the next two lines to enable the admin:
if
settings
.
DEBUG
or
settings
.
FEATURES
.
get
(
'ENABLE_DJANGO_ADMIN_SITE'
):
...
...
openedx/features/enterprise_support/README.rst
0 → 100644
View file @
3be8f92b
Enterprise Support
------------------
This directory contains a Django application to support usage of
enterprise features within edx-platform. The majority of the capabilities
are provided through the external edx-enterprise library that can be found
here: `https://github.com/edx/edx-enterprise`_.
openedx/features/enterprise_support/__init__.py
0 → 100644
View file @
3be8f92b
common/djangoapps/util/enterprise_helpers
.py
→
openedx/features/enterprise_support/api
.py
View file @
3be8f92b
"""
Helpers to access the enterprise app
APIs providing support for enterprise functionality.
"""
from
functools
import
wraps
import
hashlib
import
logging
import
six
from
functools
import
wraps
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
from
django.core.cache
import
cache
from
django.core.urlresolvers
import
reverse
from
django.shortcuts
import
redirect
from
django.template.loader
import
render_to_string
from
django.utils.http
import
urlencode
from
django.utils.translation
import
ugettext
as
_
from
edxmako.shortcuts
import
render_to_string
from
slumber.exceptions
import
HttpClientError
,
HttpServerError
from
edx_rest_api_client.client
import
EdxRestApiClient
try
:
from
enterprise
import
utils
as
enterprise_utils
...
...
@@ -25,9 +29,6 @@ from requests.exceptions import ConnectionError, Timeout
from
openedx.core.djangoapps.api_admin.utils
import
course_discovery_api_client
from
openedx.core.lib.token_utils
import
JwtBuilder
from
slumber.exceptions
import
HttpClientError
,
HttpServerError
import
hashlib
import
six
CONSENT_FAILED_PARAMETER
=
'consent_failed'
...
...
@@ -207,6 +208,12 @@ def data_sharing_consent_required(view_func):
# Redirect to the consent URL, if consent is required.
consent_url
=
get_enterprise_consent_url
(
request
,
course_id
)
if
consent_url
:
real_user
=
getattr
(
request
.
user
,
'real_user'
,
request
.
user
)
LOGGER
.
warning
(
u'User
%
s cannot access the course
%
s because they have not granted consent'
,
real_user
,
course_id
,
)
return
redirect
(
consent_url
)
# Otherwise, drop through to wrapped view
...
...
@@ -439,7 +446,7 @@ def get_dashboard_consent_notification(request, user, course_enrollments):
)
return
render_to_string
(
'
util
/enterprise_consent_declined_notification.html'
,
'
enterprise_support
/enterprise_consent_declined_notification.html'
,
{
'title'
:
title
,
'message'
:
message
,
...
...
common/templates/util
/enterprise_consent_declined_notification.html
→
openedx/features/enterprise_support/templates/enterprise_support
/enterprise_consent_declined_notification.html
View file @
3be8f92b
## mako
<
%
page
expression_filter=
"h"
/>
<div
class=
"wrapper-msg urgency-info"
>
<div
class=
"msg"
>
<span
class=
"msg-icon fa fa-info-circle"
aria-hidden=
"true"
></span>
...
...
openedx/features/enterprise_support/tests/__init__.py
0 → 100644
View file @
3be8f92b
openedx/features/enterprise_support/tests/mixins/__init__.py
0 → 100644
View file @
3be8f92b
common/djangoapps/util
/tests/mixins/enterprise.py
→
openedx/features/enterprise_support
/tests/mixins/enterprise.py
View file @
3be8f92b
...
...
@@ -147,8 +147,8 @@ class EnterpriseTestConsentRequired(object):
* url: URL to test
* status_code: expected status code of URL when no data sharing consent is required.
"""
with
mock
.
patch
(
'
util.enterprise_helpers
.enterprise_enabled'
,
return_value
=
True
):
with
mock
.
patch
(
'
util.enterprise_helpers.consent_necessary_for_course'
)
as
mock_consent_necessary
:
with
mock
.
patch
(
'
openedx.features.enterprise_support.api
.enterprise_enabled'
,
return_value
=
True
):
with
mock
.
patch
(
'
openedx.features.enterprise_support.api.consent_necessary_for_course'
)
as
mock_consent_necessary
:
# pylint: disable=line-too-long
# Ensure that when consent is necessary, the user is redirected to the consent page.
mock_consent_necessary
.
return_value
=
True
response
=
client
.
get
(
url
)
...
...
common/djangoapps/util/tests/test_enterprise_helpers
.py
→
openedx/features/enterprise_support/tests/test_api
.py
View file @
3be8f92b
"""
Test the enterprise
app helpers
Test the enterprise
support APIs.
"""
import
mock
import
unittest
from
django.conf
import
settings
from
django.http
import
HttpResponseRedirect
from
django.test.utils
import
override_settings
import
mock
from
util.enterprise_helpers
import
(
from
openedx.features.enterprise_support.api
import
(
enterprise_enabled
,
insert_enterprise_pipeline_elements
,
data_sharing_consent_required
,
...
...
@@ -21,9 +21,9 @@ from util.enterprise_helpers import (
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
class
TestEnterprise
Helpers
(
unittest
.
TestCase
):
class
TestEnterprise
Api
(
unittest
.
TestCase
):
"""
Test enterprise
app helpers
Test enterprise
support APIs.
"""
@override_settings
(
ENABLE_ENTERPRISE_INTEGRATION
=
False
)
...
...
@@ -101,7 +101,10 @@ class TestEnterpriseHelpers(unittest.TestCase):
self
.
assertEqual
(
logo_url
,
None
)
@override_settings
(
ENABLE_ENTERPRISE_INTEGRATION
=
True
)
@mock.patch
(
'util.enterprise_helpers.get_enterprise_branding_filter_param'
,
mock
.
Mock
(
return_value
=
None
))
@mock.patch
(
'openedx.features.enterprise_support.api.get_enterprise_branding_filter_param'
,
mock
.
Mock
(
return_value
=
None
)
)
def
test_get_enterprise_customer_logo_url_return_none_when_param_missing
(
self
):
"""
Test get_enterprise_customer_logo_url return 'None' when filter parameters are missing.
...
...
@@ -142,8 +145,8 @@ class TestEnterpriseHelpers(unittest.TestCase):
else
:
self
.
assertEqual
(
response
,
(
args
,
kwargs
))
@mock.patch
(
'
util.enterprise_helpers
.enterprise_enabled'
)
@mock.patch
(
'
util.enterprise_helpers
.consent_necessary_for_course'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.enterprise_enabled'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.consent_necessary_for_course'
)
def
test_data_consent_required_enterprise_disabled
(
self
,
mock_consent_necessary
,
mock_enterprise_enabled
):
...
...
@@ -158,8 +161,8 @@ class TestEnterpriseHelpers(unittest.TestCase):
mock_enterprise_enabled
.
assert_called_once
()
mock_consent_necessary
.
assert_not_called
()
@mock.patch
(
'
util.enterprise_helpers
.enterprise_enabled'
)
@mock.patch
(
'
util.enterprise_helpers
.consent_necessary_for_course'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.enterprise_enabled'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.consent_necessary_for_course'
)
def
test_no_course_data_consent_required
(
self
,
mock_consent_necessary
,
mock_enterprise_enabled
):
...
...
@@ -176,9 +179,9 @@ class TestEnterpriseHelpers(unittest.TestCase):
mock_enterprise_enabled
.
assert_called_once
()
mock_consent_necessary
.
assert_called_once
()
@mock.patch
(
'
util.enterprise_helpers
.enterprise_enabled'
)
@mock.patch
(
'
util.enterprise_helpers
.consent_necessary_for_course'
)
@mock.patch
(
'
util.enterprise_helpers
.get_enterprise_consent_url'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.enterprise_enabled'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.consent_necessary_for_course'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.get_enterprise_consent_url'
)
def
test_data_consent_required
(
self
,
mock_get_consent_url
,
mock_consent_necessary
,
mock_enterprise_enabled
):
"""
Verify that the wrapped function returns a redirect to the consent URL when enterprise integration is enabled,
...
...
@@ -195,7 +198,7 @@ class TestEnterpriseHelpers(unittest.TestCase):
mock_enterprise_enabled
.
assert_called_once
()
mock_consent_necessary
.
assert_called_once
()
@mock.patch
(
'
util.enterprise_helpers
.consent_needed_for_course'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.consent_needed_for_course'
)
def
test_get_enterprise_consent_url
(
self
,
needed_for_course_mock
):
"""
Verify that get_enterprise_consent_url correctly builds URLs.
...
...
@@ -264,7 +267,7 @@ class TestEnterpriseHelpers(unittest.TestCase):
)
self
.
assertEqual
(
notification_string
,
''
)
@mock.patch
(
'
util.enterprise_helpers
.EnterpriseCourseEnrollment'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.EnterpriseCourseEnrollment'
)
def
test_get_dashboard_consent_notification_no_contact_info
(
self
,
ece_mock
):
mock_get_ece
=
ece_mock
.
objects
.
get
ece_mock
.
DoesNotExist
=
Exception
...
...
@@ -300,7 +303,7 @@ class TestEnterpriseHelpers(unittest.TestCase):
expected_header
=
'Enrollment in edX Demo Course was not complete.'
self
.
assertIn
(
expected_header
,
notification_string
)
@mock.patch
(
'
util.enterprise_helpers
.EnterpriseCourseEnrollment'
)
@mock.patch
(
'
openedx.features.enterprise_support.api
.EnterpriseCourseEnrollment'
)
def
test_get_dashboard_consent_notification_contact_info
(
self
,
ece_mock
):
mock_get_ece
=
ece_mock
.
objects
.
get
ece_mock
.
DoesNotExist
=
Exception
...
...
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