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
b5e987ba
Commit
b5e987ba
authored
Jan 10, 2017
by
christopher lee
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MA-3091: Added mobile_available flag override admin setting
parent
6572b1df
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
148 additions
and
74 deletions
+148
-74
lms/djangoapps/courseware/access.py
+21
-15
lms/djangoapps/mobile_api/admin.py
+6
-1
lms/djangoapps/mobile_api/course_info/views.py
+1
-1
lms/djangoapps/mobile_api/decorators.py
+52
-0
lms/djangoapps/mobile_api/migrations/0003_ignore_mobile_available_flag.py
+30
-0
lms/djangoapps/mobile_api/models.py
+20
-2
lms/djangoapps/mobile_api/tests/test_decorator.py
+1
-1
lms/djangoapps/mobile_api/testutils.py
+11
-0
lms/djangoapps/mobile_api/users/serializers.py
+1
-1
lms/djangoapps/mobile_api/users/tests.py
+1
-0
lms/djangoapps/mobile_api/users/views.py
+2
-3
lms/djangoapps/mobile_api/utils.py
+1
-49
lms/djangoapps/mobile_api/video_outlines/views.py
+1
-1
No files found.
lms/djangoapps/courseware/access.py
View file @
b5e987ba
...
...
@@ -33,9 +33,25 @@ from xmodule.x_module import XModule
from
xmodule.split_test_module
import
get_split_user_partitions
from
xmodule.partitions.partitions
import
NoSuchUserPartitionError
,
NoSuchUserPartitionGroupError
from
openedx.core.djangoapps.external_auth.models
import
ExternalAuthMap
from
courseware.access_response
import
(
MilestoneError
,
MobileAvailabilityError
,
VisibilityError
,
)
from
courseware.access_utils
import
(
ACCESS_DENIED
,
ACCESS_GRANTED
,
adjust_start_date
,
check_start_date
,
debug
,
in_preview_mode
)
from
courseware.masquerade
import
get_masquerade_role
,
is_masquerading_as_student
from
lms.djangoapps.ccx.custom_exception
import
CCXLocatorValidationException
from
lms.djangoapps.ccx.models
import
CustomCourseForEdX
from
mobile_api.models
import
IgnoreMobileAvailableFlagConfig
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
openedx.core.djangoapps.external_auth.models
import
ExternalAuthMap
from
student
import
auth
from
student.models
import
CourseEnrollmentAllowed
from
student.roles
import
(
...
...
@@ -55,19 +71,6 @@ from util.milestones_helpers import (
)
from
ccx_keys.locator
import
CCXLocator
from
courseware.access_response
import
(
MilestoneError
,
MobileAvailabilityError
,
VisibilityError
,
)
from
courseware.access_utils
import
(
adjust_start_date
,
check_start_date
,
debug
,
ACCESS_GRANTED
,
ACCESS_DENIED
,
in_preview_mode
)
from
lms.djangoapps.ccx.custom_exception
import
CCXLocatorValidationException
from
lms.djangoapps.ccx.models
import
CustomCourseForEdX
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -849,7 +852,10 @@ def _is_descriptor_mobile_available(descriptor):
"""
Returns if descriptor is available on mobile.
"""
return
ACCESS_GRANTED
if
descriptor
.
mobile_available
else
MobileAvailabilityError
()
if
IgnoreMobileAvailableFlagConfig
.
is_enabled
()
or
descriptor
.
mobile_available
:
return
ACCESS_GRANTED
else
:
return
MobileAvailabilityError
()
def
is_mobile_available_for_user
(
user
,
descriptor
):
...
...
lms/djangoapps/mobile_api/admin.py
View file @
b5e987ba
...
...
@@ -4,9 +4,14 @@ Django admin dashboard configuration for LMS XBlock infrastructure.
from
django.contrib
import
admin
from
config_models.admin
import
ConfigurationModelAdmin
from
mobile_api.models
import
MobileApiConfig
,
AppVersionConfig
from
.models
import
(
AppVersionConfig
,
MobileApiConfig
,
IgnoreMobileAvailableFlagConfig
)
admin
.
site
.
register
(
MobileApiConfig
,
ConfigurationModelAdmin
)
admin
.
site
.
register
(
IgnoreMobileAvailableFlagConfig
,
ConfigurationModelAdmin
)
class
AppVersionConfigAdmin
(
admin
.
ModelAdmin
):
...
...
lms/djangoapps/mobile_api/course_info/views.py
View file @
b5e987ba
...
...
@@ -9,7 +9,7 @@ from courseware.courses import get_course_info_section_module
from
static_replace
import
make_static_urls_absolute
from
openedx.core.lib.xblock_utils
import
get_course_update_items
from
..
utils
import
mobile_view
,
mobile_course_access
from
..
decorators
import
mobile_course_access
,
mobile_view
@mobile_view
()
...
...
lms/djangoapps/mobile_api/decorators.py
0 → 100644
View file @
b5e987ba
"""
Decorators for Mobile APIs.
"""
import
functools
from
rest_framework
import
status
from
rest_framework.response
import
Response
from
lms.djangoapps.courseware.courses
import
get_course_with_access
from
lms.djangoapps.courseware.courseware_access_exception
import
CoursewareAccessException
from
opaque_keys.edx.keys
import
CourseKey
from
xmodule.modulestore.django
import
modulestore
from
openedx.core.lib.api.view_utils
import
view_auth_classes
def
mobile_course_access
(
depth
=
0
):
"""
Method decorator for a mobile API endpoint that verifies the user has access to the course in a mobile context.
"""
def
_decorator
(
func
):
"""Outer method decorator."""
@functools.wraps
(
func
)
def
_wrapper
(
self
,
request
,
*
args
,
**
kwargs
):
"""
Expects kwargs to contain 'course_id'.
Passes the course descriptor to the given decorated function.
Raises 404 if access to course is disallowed.
"""
course_id
=
CourseKey
.
from_string
(
kwargs
.
pop
(
'course_id'
))
with
modulestore
()
.
bulk_operations
(
course_id
):
try
:
course
=
get_course_with_access
(
request
.
user
,
'load_mobile'
,
course_id
,
depth
=
depth
,
check_if_enrolled
=
True
,
)
except
CoursewareAccessException
as
error
:
return
Response
(
data
=
error
.
to_json
(),
status
=
status
.
HTTP_404_NOT_FOUND
)
return
func
(
self
,
request
,
course
=
course
,
*
args
,
**
kwargs
)
return
_wrapper
return
_decorator
def
mobile_view
(
is_user
=
False
):
"""
Function and class decorator that abstracts the authentication and permission checks for mobile api views.
"""
return
view_auth_classes
(
is_user
)
lms/djangoapps/mobile_api/migrations/0003_ignore_mobile_available_flag.py
0 → 100644
View file @
b5e987ba
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
from
django.conf
import
settings
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
migrations
.
swappable_dependency
(
settings
.
AUTH_USER_MODEL
),
(
'mobile_api'
,
'0002_auto_20160406_0904'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'IgnoreMobileAvailableFlagConfig'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
verbose_name
=
'ID'
,
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
)),
(
'change_date'
,
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
'Change date'
)),
(
'enabled'
,
models
.
BooleanField
(
default
=
False
,
verbose_name
=
'Enabled'
)),
(
'changed_by'
,
models
.
ForeignKey
(
on_delete
=
django
.
db
.
models
.
deletion
.
PROTECT
,
editable
=
False
,
to
=
settings
.
AUTH_USER_MODEL
,
null
=
True
,
verbose_name
=
'Changed by'
)),
],
),
migrations
.
AlterModelOptions
(
name
=
'mobileapiconfig'
,
options
=
{},
),
]
lms/djangoapps/mobile_api/models.py
View file @
b5e987ba
...
...
@@ -2,9 +2,10 @@
ConfigurationModel for the mobile_api djangoapp.
"""
from
django.db
import
models
from
mobile_api
import
utils
from
config_models.models
import
ConfigurationModel
from
mobile_api.mobile_platform
import
PLATFORM_CLASSES
from
.mobile_platform
import
PLATFORM_CLASSES
from
.
import
utils
class
MobileApiConfig
(
ConfigurationModel
):
...
...
@@ -19,6 +20,9 @@ class MobileApiConfig(ConfigurationModel):
help_text
=
"A comma-separated list of names of profiles to include for videos returned from the mobile API."
)
class
Meta
(
object
):
app_label
=
"mobile_api"
@classmethod
def
get_video_profiles
(
cls
):
"""
...
...
@@ -50,6 +54,7 @@ class AppVersionConfig(models.Model):
updated_at
=
models
.
DateTimeField
(
auto_now
=
True
)
class
Meta
:
app_label
=
"mobile_api"
unique_together
=
(
'platform'
,
'version'
,)
ordering
=
[
'-major_version'
,
'-minor_version'
,
'-patch_version'
]
...
...
@@ -76,3 +81,16 @@ class AppVersionConfig(models.Model):
""" parses version into major, minor and patch versions before saving """
self
.
major_version
,
self
.
minor_version
,
self
.
patch_version
=
utils
.
parsed_version
(
self
.
version
)
super
(
AppVersionConfig
,
self
)
.
save
(
*
args
,
**
kwargs
)
class
IgnoreMobileAvailableFlagConfig
(
ConfigurationModel
):
# pylint: disable=W5101
"""
Configuration for the mobile_available flag. Default is false.
Enabling this configuration will cause the mobile_available flag check in
access.py._is_descriptor_mobile_available to ignore the mobile_available
flag.
"""
class
Meta
(
object
):
app_label
=
"mobile_api"
lms/djangoapps/mobile_api/tests/test_decorator.py
View file @
b5e987ba
...
...
@@ -6,7 +6,7 @@ Tests for mobile API utilities.
import
ddt
from
django.test
import
TestCase
from
mobile_api.util
s
import
mobile_course_access
,
mobile_view
from
..decorator
s
import
mobile_course_access
,
mobile_view
@ddt.ddt
...
...
lms/djangoapps/mobile_api/testutils.py
View file @
b5e987ba
...
...
@@ -30,6 +30,7 @@ from courseware.access_response import (
from
courseware.tests.factories
import
UserFactory
from
student
import
auth
from
student.models
import
CourseEnrollment
from
mobile_api.models
import
IgnoreMobileAvailableFlagConfig
from
mobile_api.tests.test_milestones
import
MobileAPIMilestonesMixin
...
...
@@ -46,6 +47,7 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase):
self
.
user
=
UserFactory
.
create
()
self
.
password
=
'test'
self
.
username
=
self
.
user
.
username
IgnoreMobileAvailableFlagConfig
(
enabled
=
False
)
.
save
()
def
tearDown
(
self
):
super
(
MobileAPITestCase
,
self
)
.
tearDown
()
...
...
@@ -188,12 +190,21 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin):
@ddt.unpack
@patch.dict
(
settings
.
FEATURES
,
{
'ENABLE_MKTG_SITE'
:
True
})
def
test_non_mobile_available
(
self
,
role
,
should_succeed
):
"""
Tests that the MobileAvailabilityError() is raised for certain user
roles when trying to access course content. Also verifies that if
the IgnoreMobileAvailableFlagConfig is enabled,
MobileAvailabilityError() will not be raised for all user roles.
"""
self
.
init_course_access
()
# set mobile_available to False for the test course
self
.
course
.
mobile_available
=
False
self
.
store
.
update_item
(
self
.
course
,
self
.
user
.
id
)
self
.
_verify_response
(
should_succeed
,
MobileAvailabilityError
(),
role
)
IgnoreMobileAvailableFlagConfig
(
enabled
=
True
)
.
save
()
self
.
_verify_response
(
True
,
MobileAvailabilityError
(),
role
)
def
test_unenrolled_user
(
self
):
self
.
login
()
self
.
unenroll
()
...
...
lms/djangoapps/mobile_api/users/serializers.py
View file @
b5e987ba
...
...
@@ -5,9 +5,9 @@ from opaque_keys.edx.keys import CourseKey
from
rest_framework
import
serializers
from
rest_framework.reverse
import
reverse
from
certificates.api
import
certificate_downloadable_status
from
courseware.access
import
has_access
from
student.models
import
CourseEnrollment
,
User
from
certificates.api
import
certificate_downloadable_status
from
util.course
import
get_lms_link_for_about_page
...
...
lms/djangoapps/mobile_api/users/tests.py
View file @
b5e987ba
...
...
@@ -37,6 +37,7 @@ from mobile_api.testutils import (
MobileAuthUserTestMixin
,
MobileCourseAccessTestMixin
,
)
from
.serializers
import
CourseEnrollmentSerializer
...
...
lms/djangoapps/mobile_api/users/views.py
View file @
b5e987ba
...
...
@@ -26,7 +26,7 @@ from xmodule.modulestore.exceptions import ItemNotFoundError
from
.serializers
import
CourseEnrollmentSerializer
,
UserSerializer
from
..
import
errors
from
..
utils
import
mobile_view
,
mobile_course_access
from
..
decorators
import
mobile_course_access
,
mobile_view
@mobile_view
(
is_user
=
True
)
...
...
@@ -60,8 +60,7 @@ class UserDetail(generics.RetrieveAPIView):
* username: The username of the currently signed in user.
"""
queryset
=
(
User
.
objects
.
all
()
.
select_related
(
'profile'
)
User
.
objects
.
all
()
.
select_related
(
'profile'
)
)
serializer_class
=
UserSerializer
lookup_field
=
'username'
...
...
lms/djangoapps/mobile_api/utils.py
View file @
b5e987ba
"""
Common utility methods
and decorators
for Mobile APIs.
Common utility methods for Mobile APIs.
"""
import
functools
from
rest_framework
import
status
from
rest_framework.response
import
Response
from
lms.djangoapps.courseware.courses
import
get_course_with_access
from
lms.djangoapps.courseware.courseware_access_exception
import
CoursewareAccessException
from
opaque_keys.edx.keys
import
CourseKey
from
openedx.core.lib.api.view_utils
import
view_auth_classes
from
xmodule.modulestore.django
import
modulestore
def
mobile_course_access
(
depth
=
0
):
"""
Method decorator for a mobile API endpoint that verifies the user has access to the course in a mobile context.
"""
def
_decorator
(
func
):
"""Outer method decorator."""
@functools.wraps
(
func
)
def
_wrapper
(
self
,
request
,
*
args
,
**
kwargs
):
"""
Expects kwargs to contain 'course_id'.
Passes the course descriptor to the given decorated function.
Raises 404 if access to course is disallowed.
"""
course_id
=
CourseKey
.
from_string
(
kwargs
.
pop
(
'course_id'
))
with
modulestore
()
.
bulk_operations
(
course_id
):
try
:
course
=
get_course_with_access
(
request
.
user
,
'load_mobile'
,
course_id
,
depth
=
depth
,
check_if_enrolled
=
True
,
)
except
CoursewareAccessException
as
error
:
return
Response
(
data
=
error
.
to_json
(),
status
=
status
.
HTTP_404_NOT_FOUND
)
return
func
(
self
,
request
,
course
=
course
,
*
args
,
**
kwargs
)
return
_wrapper
return
_decorator
def
mobile_view
(
is_user
=
False
):
"""
Function and class decorator that abstracts the authentication and permission checks for mobile api views.
"""
return
view_auth_classes
(
is_user
)
def
parsed_version
(
version
):
...
...
lms/djangoapps/mobile_api/video_outlines/views.py
View file @
b5e987ba
...
...
@@ -18,7 +18,7 @@ from opaque_keys.edx.locator import BlockUsageLocator
from
xmodule.exceptions
import
NotFoundError
from
xmodule.modulestore.django
import
modulestore
from
..
utils
import
mobile_view
,
mobile_course_access
from
..
decorators
import
mobile_course_access
,
mobile_view
from
.serializers
import
BlockOutline
,
video_summary
...
...
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