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
8394fb71
Commit
8394fb71
authored
Jan 16, 2015
by
Nimisha Asthagiri
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6608 from edx/mobile/MA-216
MA-216 Mobile API: display unreleased courses in enrollment list.
parents
314ad957
dea6b764
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
60 additions
and
84 deletions
+60
-84
lms/djangoapps/courseware/access.py
+15
-5
lms/djangoapps/mobile_api/tests.py
+1
-41
lms/djangoapps/mobile_api/testutils.py
+13
-11
lms/djangoapps/mobile_api/users/tests.py
+19
-1
lms/djangoapps/mobile_api/users/views.py
+12
-9
lms/djangoapps/mobile_api/utils.py
+0
-17
No files found.
lms/djangoapps/courseware/access.py
View file @
8394fb71
...
...
@@ -166,11 +166,7 @@ def _has_access_course_desc(user, action, course):
# check start date
can_load
()
and
# check mobile_available flag
(
course
.
mobile_available
or
auth
.
has_access
(
user
,
CourseBetaTesterRole
(
course
.
id
))
or
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
)
is_mobile_available_for_user
(
user
,
course
)
)
def
can_enroll
():
...
...
@@ -649,6 +645,20 @@ def _has_staff_access_to_descriptor(user, descriptor, course_key):
return
_has_staff_access_to_location
(
user
,
descriptor
.
location
,
course_key
)
def
is_mobile_available_for_user
(
user
,
course
):
"""
Returns whether the given course is mobile_available for the given user.
Checks:
mobile_available flag on the course
Beta User and staff access overrides the mobile_available flag
"""
return
(
course
.
mobile_available
or
auth
.
has_access
(
user
,
CourseBetaTesterRole
(
course
.
id
))
or
_has_staff_access_to_descriptor
(
user
,
course
,
course
.
id
)
)
def
get_user_role
(
user
,
course_key
):
"""
Return corresponding string if user has staff, instructor or student
...
...
lms/djangoapps/mobile_api/tests.py
View file @
8394fb71
...
...
@@ -3,49 +3,9 @@ Tests for mobile API utilities.
"""
import
ddt
from
mock
import
patch
from
django.test
import
TestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
.utils
import
mobile_access_when_enrolled
,
mobile_course_access
,
mobile_view
from
.testutils
import
MobileAPITestCase
,
ROLE_CASES
@ddt.ddt
class
TestMobileAccessWhenEnrolled
(
MobileAPITestCase
):
"""
Tests for mobile_access_when_enrolled utility function.
"""
@ddt.data
(
*
ROLE_CASES
)
@ddt.unpack
def
test_mobile_role_access
(
self
,
role
,
should_have_access
):
"""
Verifies that our mobile access function properly handles using roles to grant access
"""
non_mobile_course
=
CourseFactory
.
create
(
mobile_available
=
False
)
if
role
:
role
(
non_mobile_course
.
id
)
.
add_users
(
self
.
user
)
self
.
assertEqual
(
should_have_access
,
mobile_access_when_enrolled
(
non_mobile_course
,
self
.
user
))
def
test_mobile_explicit_access
(
self
):
"""
Verifies that our mobile access function listens to the mobile_available flag as it should
"""
self
.
assertTrue
(
mobile_access_when_enrolled
(
self
.
course
,
self
.
user
))
def
test_missing_course
(
self
):
"""
Verifies that we handle the case where a course doesn't exist
"""
self
.
assertFalse
(
mobile_access_when_enrolled
(
None
,
self
.
user
))
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
def
test_unreleased_course
(
self
):
"""
Verifies that we handle the case where a course hasn't started
"""
self
.
assertFalse
(
mobile_access_when_enrolled
(
self
.
course
,
self
.
user
))
from
.utils
import
mobile_course_access
,
mobile_view
@ddt.ddt
...
...
lms/djangoapps/mobile_api/testutils.py
View file @
8394fb71
...
...
@@ -26,15 +26,6 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
# A tuple of Role Types and Boolean values that indicate whether access should be given to that role.
ROLE_CASES
=
(
(
auth
.
CourseBetaTesterRole
,
True
),
(
auth
.
CourseStaffRole
,
True
),
(
auth
.
CourseInstructorRole
,
True
),
(
None
,
False
)
)
class
MobileAPITestCase
(
ModuleStoreTestCase
,
APITestCase
):
"""
Base class for testing Mobile APIs.
...
...
@@ -140,6 +131,8 @@ class MobileCourseAccessTestMixin(object):
Subclasses are expected to inherit from MobileAPITestCase.
Subclasses can override verify_success, verify_failure, and init_course_access methods.
"""
ALLOW_ACCESS_TO_UNRELEASED_COURSE
=
False
# pylint: disable=invalid-name
def
verify_success
(
self
,
response
):
"""Base implementation of verifying a successful response."""
self
.
assertEqual
(
response
.
status_code
,
200
)
...
...
@@ -170,9 +163,18 @@ class MobileCourseAccessTestMixin(object):
self
.
init_course_access
()
response
=
self
.
api_response
(
expected_response_code
=
None
)
self
.
verify_failure
(
response
)
# allow subclasses to override verification
if
self
.
ALLOW_ACCESS_TO_UNRELEASED_COURSE
:
self
.
verify_success
(
response
)
else
:
self
.
verify_failure
(
response
)
@ddt.data
(
*
ROLE_CASES
)
# A tuple of Role Types and Boolean values that indicate whether access should be given to that role.
@ddt.data
(
(
auth
.
CourseBetaTesterRole
,
True
),
(
auth
.
CourseStaffRole
,
True
),
(
auth
.
CourseInstructorRole
,
True
),
(
None
,
False
)
)
@ddt.unpack
def
test_non_mobile_available
(
self
,
role
,
should_succeed
):
self
.
init_course_access
()
...
...
lms/djangoapps/mobile_api/users/tests.py
View file @
8394fb71
...
...
@@ -5,7 +5,7 @@ Tests for users API
import
datetime
from
django.utils
import
timezone
from
xmodule.modulestore.tests.factories
import
ItemFactory
from
xmodule.modulestore.tests.factories
import
ItemFactory
,
CourseFactory
from
xmodule.modulestore.django
import
modulestore
from
student.models
import
CourseEnrollment
...
...
@@ -48,6 +48,7 @@ class TestUserEnrollmentApi(MobileAPITestCase, MobileAuthUserTestMixin, MobileEn
Tests for /api/mobile/v0.5/users/<user_name>/course_enrollments/
"""
REVERSE_INFO
=
{
'name'
:
'courseenrollment-detail'
,
'params'
:
[
'username'
]}
ALLOW_ACCESS_TO_UNRELEASED_COURSE
=
True
def
verify_success
(
self
,
response
):
super
(
TestUserEnrollmentApi
,
self
)
.
verify_success
(
response
)
...
...
@@ -65,6 +66,23 @@ class TestUserEnrollmentApi(MobileAPITestCase, MobileAuthUserTestMixin, MobileEn
courses
=
response
.
data
self
.
assertEqual
(
len
(
courses
),
0
)
def
test_sort_order
(
self
):
self
.
login
()
num_courses
=
3
courses
=
[]
for
course_num
in
range
(
num_courses
):
courses
.
append
(
CourseFactory
.
create
(
mobile_available
=
True
))
self
.
enroll
(
courses
[
course_num
]
.
id
)
# verify courses are returned in the order of enrollment, with most recently enrolled first.
response
=
self
.
api_response
()
for
course_num
in
range
(
num_courses
):
self
.
assertEqual
(
response
.
data
[
course_num
][
'course'
][
'id'
],
# pylint: disable=no-member
unicode
(
courses
[
num_courses
-
course_num
-
1
]
.
id
)
)
class
CourseStatusAPITestCase
(
MobileAPITestCase
):
"""
...
...
lms/djangoapps/mobile_api/users/views.py
View file @
8394fb71
...
...
@@ -2,9 +2,6 @@
Views for user API
"""
from
courseware.model_data
import
FieldDataCache
from
courseware.module_render
import
get_module_for_descriptor
from
django.shortcuts
import
redirect
from
django.utils
import
dateparse
...
...
@@ -12,11 +9,13 @@ from rest_framework import generics, views
from
rest_framework.decorators
import
api_view
from
rest_framework.response
import
Response
from
courseware.views
import
get_current_child
,
save_positions_recursively_up
from
opaque_keys.edx.keys
import
UsageKey
from
opaque_keys
import
InvalidKeyError
from
courseware.access
import
is_mobile_available_for_user
from
courseware.model_data
import
FieldDataCache
from
courseware.module_render
import
get_module_for_descriptor
from
courseware.views
import
get_current_child
,
save_positions_recursively_up
from
student.models
import
CourseEnrollment
,
User
from
xblock.fields
import
Scope
...
...
@@ -25,8 +24,8 @@ from xmodule.modulestore.django import modulestore
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
.serializers
import
CourseEnrollmentSerializer
,
UserSerializer
from
mobile_api
import
errors
from
mobile_api.utils
import
mobile_access_when_enrolled
,
mobile_view
,
mobile_course_access
from
..
import
errors
from
..utils
import
mobile_view
,
mobile_course_access
@mobile_view
(
is_user
=
True
)
...
...
@@ -46,6 +45,7 @@ class UserDetail(generics.RetrieveAPIView):
GET /api/mobile/v0.5/users/{username}
**Response Values**
* id: The ID of the user.
...
...
@@ -241,10 +241,13 @@ class UserCourseEnrollmentsList(generics.ListAPIView):
lookup_field
=
'username'
def
get_queryset
(
self
):
enrollments
=
self
.
queryset
.
filter
(
user__username
=
self
.
kwargs
[
'username'
],
is_active
=
True
)
.
order_by
(
'created'
)
enrollments
=
self
.
queryset
.
filter
(
user__username
=
self
.
kwargs
[
'username'
],
is_active
=
True
)
.
order_by
(
'created'
)
.
reverse
()
return
[
enrollment
for
enrollment
in
enrollments
if
mobile_access_when_enrolled
(
enrollment
.
course
,
self
.
request
.
user
)
if
enrollment
.
course
and
is_mobile_available_for_user
(
self
.
request
.
user
,
enrollment
.
course
)
]
...
...
lms/djangoapps/mobile_api/utils.py
View file @
8394fb71
...
...
@@ -4,7 +4,6 @@ Common utility methods and decorators for Mobile APIs.
import
functools
from
django.http
import
Http404
from
opaque_keys.edx.keys
import
CourseKey
from
courseware.courses
import
get_course_with_access
...
...
@@ -37,22 +36,6 @@ def mobile_course_access(depth=0, verify_enrolled=True):
return
_decorator
def
mobile_access_when_enrolled
(
course
,
user
):
"""
Determines whether a user has access to a course in a mobile context.
Checks the mobile_available flag and the start_date.
Note: Does not check if the user is actually enrolled in the course.
"""
# The course doesn't always really exist -- we can have bad data in the enrollments
# pointing to non-existent (or removed) courses, in which case `course` is None.
if
not
course
:
return
False
try
:
return
get_course_with_access
(
user
,
'load_mobile_no_enrollment_check'
,
course
.
id
)
is
not
None
except
Http404
:
return
False
def
mobile_view
(
is_user
=
False
):
"""
Function and class decorator that abstracts the authentication and permission checks for mobile api views.
...
...
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