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
fa8ca11d
Commit
fa8ca11d
authored
Jan 25, 2016
by
Nimisha Asthagiri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove unused Mobile Social Facebook endpoint
parent
080b7d7b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
19 additions
and
1260 deletions
+19
-1260
cms/djangoapps/models/settings/course_metadata.py
+0
-4
common/lib/xmodule/xmodule/course_module.py
+0
-9
lms/djangoapps/mobile_api/social_facebook/__init__.py
+0
-42
lms/djangoapps/mobile_api/social_facebook/courses/__init__.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/courses/models.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/courses/serializers.py
+0
-11
lms/djangoapps/mobile_api/social_facebook/courses/tests.py
+0
-147
lms/djangoapps/mobile_api/social_facebook/courses/urls.py
+0
-15
lms/djangoapps/mobile_api/social_facebook/courses/views.py
+0
-65
lms/djangoapps/mobile_api/social_facebook/friends/__init__.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/friends/models.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/friends/serializers.py
+0
-11
lms/djangoapps/mobile_api/social_facebook/friends/tests.py
+0
-0
lms/djangoapps/mobile_api/social_facebook/friends/urls.py
+0
-16
lms/djangoapps/mobile_api/social_facebook/friends/views.py
+0
-71
lms/djangoapps/mobile_api/social_facebook/groups/__init__.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/groups/models.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/groups/serializers.py
+0
-30
lms/djangoapps/mobile_api/social_facebook/groups/tests.py
+0
-199
lms/djangoapps/mobile_api/social_facebook/groups/urls.py
+0
-20
lms/djangoapps/mobile_api/social_facebook/groups/views.py
+0
-143
lms/djangoapps/mobile_api/social_facebook/models.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/preferences/__init__.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/preferences/models.py
+0
-3
lms/djangoapps/mobile_api/social_facebook/preferences/serializers.py
+0
-11
lms/djangoapps/mobile_api/social_facebook/preferences/tests.py
+0
-67
lms/djangoapps/mobile_api/social_facebook/preferences/urls.py
+0
-14
lms/djangoapps/mobile_api/social_facebook/preferences/views.py
+0
-52
lms/djangoapps/mobile_api/social_facebook/test_utils.py
+0
-186
lms/djangoapps/mobile_api/social_facebook/urls.py
+0
-11
lms/djangoapps/mobile_api/social_facebook/utils.py
+0
-76
lms/djangoapps/mobile_api/urls.py
+0
-7
lms/djangoapps/mobile_api/users/serializers.py
+1
-4
lms/djangoapps/mobile_api/users/tests.py
+0
-17
lms/envs/common.py
+0
-1
lms/envs/test.py
+0
-1
openedx/core/djangoapps/content/course_overviews/migrations/0008_remove_courseoverview_facebook_url.py
+18
-0
openedx/core/djangoapps/content/course_overviews/models.py
+0
-2
openedx/core/djangoapps/content/course_overviews/tests.py
+0
-1
No files found.
cms/djangoapps/models/settings/course_metadata.py
View file @
fa8ca11d
...
...
@@ -73,10 +73,6 @@ class CourseMetadata(object):
if
not
settings
.
FEATURES
.
get
(
'ENABLE_VIDEO_UPLOAD_PIPELINE'
):
filtered_list
.
append
(
'video_upload_pipeline'
)
# Do not show facebook_url if the feature is disabled.
if
not
settings
.
FEATURES
.
get
(
'ENABLE_MOBILE_SOCIAL_FACEBOOK_FEATURES'
):
filtered_list
.
append
(
'facebook_url'
)
# Do not show social sharing url field if the feature is disabled.
if
(
not
hasattr
(
settings
,
'SOCIAL_SHARING_SETTINGS'
)
or
not
getattr
(
settings
,
'SOCIAL_SHARING_SETTINGS'
,
{})
.
get
(
"CUSTOM_COURSE_URLS"
)):
...
...
common/lib/xmodule/xmodule/course_module.py
View file @
fa8ca11d
...
...
@@ -338,15 +338,6 @@ class CourseFields(object):
help
=
_
(
"Enter the unique identifier for your course's video files provided by edX."
),
scope
=
Scope
.
settings
)
facebook_url
=
String
(
help
=
_
(
"Enter the URL for the official course Facebook group. "
"If you provide a URL, the mobile app includes a button that students can tap to access the group."
),
default
=
None
,
display_name
=
_
(
"Facebook URL"
),
scope
=
Scope
.
settings
)
no_grade
=
Boolean
(
display_name
=
_
(
"Course Not Graded"
),
help
=
_
(
"Enter true or false. If true, the course will not be graded."
),
...
...
lms/djangoapps/mobile_api/social_facebook/__init__.py
deleted
100644 → 0
View file @
080b7d7b
"""
Social Facebook API
"""
# TODO
# There are still some performance and scalability issues that should be
# addressed for the various endpoints in this social_facebook djangoapp.
#
# For the Courses and Friends API:
# For both endpoints, we are retrieving the same data from the Facebook server.
# We are then simply organizing and filtering that data differently for each endpoint.
#
# Here are 3 ideas that can be explored further:
#
# Option 1. The app can just call one endpoint that provides a mapping between CourseIDs and Friends,
# and then cache that data once. The reverse map from Friends to CourseIDs can then be created on the app side.
#
# Option 2. The app once again calls just one endpoint (since the same data is computed for both),
# and caches the data once. The difference from #1 is that the server does the computation of the reverse-map and
# sends both maps down to the client. It's a tradeoff between bandwidth and client-side computation. So the payload
# could be something like:
#
# {
# courses: [
# {course_id: "c/ourse/1", friend_indices: [1, 2, 3]},
# {course_id: "c/ourse/2", friend_indices: [3, 4, 5]},
# ..
# ],
# friends: [
# {username: "friend1", facebook_id: "xxx", course_indices: [2, 7, 9]},
# {username: "friend2", facebook_id: "yyy", course_indices: [1, 4, 3]},
# ...
# ]
# }
#
# Option 3. Alternatively, continue to have separate endpoints, but have both endpoints call the same underlying method
# with a built-in cache.
#
# All 3 options can make use of a common cache of results from FB.
#
# At a minimum, some performance/load testing would need to be done
# so we have an idea of these endpoints' limitations and thresholds.
lms/djangoapps/mobile_api/social_facebook/courses/__init__.py
deleted
100644 → 0
View file @
080b7d7b
"""
Courses API
"""
lms/djangoapps/mobile_api/social_facebook/courses/models.py
deleted
100644 → 0
View file @
080b7d7b
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/social_facebook/courses/serializers.py
deleted
100644 → 0
View file @
080b7d7b
"""
Serializer for courses API
"""
from
rest_framework
import
serializers
class
CoursesWithFriendsSerializer
(
serializers
.
Serializer
):
"""
Serializes oauth token for facebook groups request
"""
oauth_token
=
serializers
.
CharField
(
required
=
True
)
lms/djangoapps/mobile_api/social_facebook/courses/tests.py
deleted
100644 → 0
View file @
080b7d7b
# pylint: disable=E1101, W0201
"""
Tests for Courses
"""
import
httpretty
import
json
from
django.core.urlresolvers
import
reverse
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
opaque_keys.edx.keys
import
CourseKey
from
..test_utils
import
SocialFacebookTestCase
class
TestCourses
(
SocialFacebookTestCase
):
"""
Tests for /api/mobile/v0.5/courses/...
"""
def
setUp
(
self
):
super
(
TestCourses
,
self
)
.
setUp
()
self
.
course
=
CourseFactory
.
create
(
mobile_available
=
True
)
@httpretty.activate
def
test_one_course_with_friends
(
self
):
self
.
user_create_and_signin
(
1
)
self
.
link_edx_account_to_social
(
self
.
users
[
1
],
self
.
BACKEND
,
self
.
USERS
[
1
][
'FB_ID'
])
self
.
set_sharing_preferences
(
self
.
users
[
1
],
True
)
self
.
set_facebook_interceptor_for_friends
(
{
'data'
:
[{
'name'
:
self
.
USERS
[
1
][
'USERNAME'
],
'id'
:
self
.
USERS
[
1
][
'FB_ID'
]}]}
)
self
.
enroll_in_course
(
self
.
users
[
1
],
self
.
course
)
url
=
reverse
(
'courses-with-friends'
)
response
=
self
.
client
.
get
(
url
,
{
'oauth_token'
:
self
.
_FB_USER_ACCESS_TOKEN
})
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
self
.
course
.
id
,
CourseKey
.
from_string
(
response
.
data
[
0
][
'course'
][
'id'
]))
# pylint: disable=E1101
@httpretty.activate
def
test_two_courses_with_friends
(
self
):
self
.
user_create_and_signin
(
1
)
self
.
link_edx_account_to_social
(
self
.
users
[
1
],
self
.
BACKEND
,
self
.
USERS
[
1
][
'FB_ID'
])
self
.
set_sharing_preferences
(
self
.
users
[
1
],
True
)
self
.
enroll_in_course
(
self
.
users
[
1
],
self
.
course
)
self
.
course_2
=
CourseFactory
.
create
(
mobile_available
=
True
)
self
.
enroll_in_course
(
self
.
users
[
1
],
self
.
course_2
)
self
.
set_facebook_interceptor_for_friends
(
{
'data'
:
[{
'name'
:
self
.
USERS
[
2
][
'USERNAME'
],
'id'
:
self
.
USERS
[
1
][
'FB_ID'
]}]}
)
url
=
reverse
(
'courses-with-friends'
)
response
=
self
.
client
.
get
(
url
,
{
'oauth_token'
:
self
.
_FB_USER_ACCESS_TOKEN
})
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
self
.
course
.
id
,
CourseKey
.
from_string
(
response
.
data
[
0
][
'course'
][
'id'
]))
# pylint: disable=E1101
self
.
assertEqual
(
self
.
course_2
.
id
,
CourseKey
.
from_string
(
response
.
data
[
1
][
'course'
][
'id'
]))
# pylint: disable=E1101
@httpretty.activate
def
test_three_courses_but_only_two_unique
(
self
):
self
.
user_create_and_signin
(
1
)
self
.
link_edx_account_to_social
(
self
.
users
[
1
],
self
.
BACKEND
,
self
.
USERS
[
1
][
'FB_ID'
])
self
.
set_sharing_preferences
(
self
.
users
[
1
],
True
)
self
.
course_2
=
CourseFactory
.
create
(
mobile_available
=
True
)
self
.
enroll_in_course
(
self
.
users
[
1
],
self
.
course_2
)
self
.
enroll_in_course
(
self
.
users
[
1
],
self
.
course
)
self
.
user_create_and_signin
(
2
)
self
.
link_edx_account_to_social
(
self
.
users
[
2
],
self
.
BACKEND
,
self
.
USERS
[
2
][
'FB_ID'
])
self
.
set_sharing_preferences
(
self
.
users
[
2
],
True
)
# Enroll another user in course_2
self
.
enroll_in_course
(
self
.
users
[
2
],
self
.
course_2
)
self
.
set_facebook_interceptor_for_friends
(
{
'data'
:
[
{
'name'
:
self
.
USERS
[
1
][
'USERNAME'
],
'id'
:
self
.
USERS
[
1
][
'FB_ID'
]},
{
'name'
:
self
.
USERS
[
2
][
'USERNAME'
],
'id'
:
self
.
USERS
[
2
][
'FB_ID'
]},
]}
)
url
=
reverse
(
'courses-with-friends'
)
response
=
self
.
client
.
get
(
url
,
{
'oauth_token'
:
self
.
_FB_USER_ACCESS_TOKEN
})
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
self
.
course
.
id
,
CourseKey
.
from_string
(
response
.
data
[
0
][
'course'
][
'id'
]))
# pylint: disable=E1101
self
.
assertEqual
(
self
.
course_2
.
id
,
CourseKey
.
from_string
(
response
.
data
[
1
][
'course'
][
'id'
]))
# pylint: disable=E1101
# Assert that only two courses are returned
self
.
assertEqual
(
len
(
response
.
data
),
2
)
# pylint: disable=E1101
@httpretty.activate
def
test_two_courses_with_two_friends_on_different_paged_results
(
self
):
self
.
user_create_and_signin
(
1
)
self
.
link_edx_account_to_social
(
self
.
users
[
1
],
self
.
BACKEND
,
self
.
USERS
[
1
][
'FB_ID'
])
self
.
set_sharing_preferences
(
self
.
users
[
1
],
True
)
self
.
enroll_in_course
(
self
.
users
[
1
],
self
.
course
)
self
.
user_create_and_signin
(
2
)
self
.
link_edx_account_to_social
(
self
.
users
[
2
],
self
.
BACKEND
,
self
.
USERS
[
2
][
'FB_ID'
])
self
.
set_sharing_preferences
(
self
.
users
[
2
],
True
)
self
.
course_2
=
CourseFactory
.
create
(
mobile_available
=
True
)
self
.
enroll_in_course
(
self
.
users
[
2
],
self
.
course_2
)
self
.
set_facebook_interceptor_for_friends
(
{
'data'
:
[{
'name'
:
self
.
USERS
[
1
][
'USERNAME'
],
'id'
:
self
.
USERS
[
1
][
'FB_ID'
]}],
"paging"
:
{
"next"
:
"https://graph.facebook.com/v2.2/me/friends/next"
},
"summary"
:
{
"total_count"
:
652
}
}
)
# Set the interceptor for the paged
httpretty
.
register_uri
(
httpretty
.
GET
,
"https://graph.facebook.com/v2.2/me/friends/next"
,
body
=
json
.
dumps
(
{
"data"
:
[{
'name'
:
self
.
USERS
[
2
][
'USERNAME'
],
'id'
:
self
.
USERS
[
2
][
'FB_ID'
]}],
"paging"
:
{
"previous"
:
"https://graph.facebook.com/v2.2/10154805434030300/friends?limit=25&offset=25"
},
"summary"
:
{
"total_count"
:
652
}
}
),
status
=
201
)
url
=
reverse
(
'courses-with-friends'
)
response
=
self
.
client
.
get
(
url
,
{
'oauth_token'
:
self
.
_FB_USER_ACCESS_TOKEN
})
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
self
.
course
.
id
,
CourseKey
.
from_string
(
response
.
data
[
0
][
'course'
][
'id'
]))
# pylint: disable=E1101
self
.
assertEqual
(
self
.
course_2
.
id
,
CourseKey
.
from_string
(
response
.
data
[
1
][
'course'
][
'id'
]))
# pylint: disable=E1101
@httpretty.activate
def
test_no_courses_with_friends_because_sharing_pref_off
(
self
):
self
.
user_create_and_signin
(
1
)
self
.
link_edx_account_to_social
(
self
.
users
[
1
],
self
.
BACKEND
,
self
.
USERS
[
1
][
'FB_ID'
])
self
.
set_sharing_preferences
(
self
.
users
[
1
],
False
)
self
.
set_facebook_interceptor_for_friends
(
{
'data'
:
[{
'name'
:
self
.
USERS
[
1
][
'USERNAME'
],
'id'
:
self
.
USERS
[
1
][
'FB_ID'
]}]}
)
self
.
enroll_in_course
(
self
.
users
[
1
],
self
.
course
)
url
=
reverse
(
'courses-with-friends'
)
response
=
self
.
client
.
get
(
url
,
{
'oauth_token'
:
self
.
_FB_USER_ACCESS_TOKEN
})
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
len
(
response
.
data
),
0
)
@httpretty.activate
def
test_no_courses_with_friends_because_no_auth_token
(
self
):
self
.
user_create_and_signin
(
1
)
self
.
link_edx_account_to_social
(
self
.
users
[
1
],
self
.
BACKEND
,
self
.
USERS
[
1
][
'FB_ID'
])
self
.
set_sharing_preferences
(
self
.
users
[
1
],
False
)
self
.
set_facebook_interceptor_for_friends
(
{
'data'
:
[{
'name'
:
self
.
USERS
[
1
][
'USERNAME'
],
'id'
:
self
.
USERS
[
1
][
'FB_ID'
]}]}
)
self
.
enroll_in_course
(
self
.
users
[
1
],
self
.
course
)
url
=
reverse
(
'courses-with-friends'
)
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
400
)
lms/djangoapps/mobile_api/social_facebook/courses/urls.py
deleted
100644 → 0
View file @
080b7d7b
"""
URLs for courses API
"""
from
django.conf.urls
import
patterns
,
url
from
.views
import
CoursesWithFriends
urlpatterns
=
patterns
(
'mobile_api.social_facebook.courses.views'
,
url
(
r'^friends$'
,
CoursesWithFriends
.
as_view
(),
name
=
'courses-with-friends'
),
)
lms/djangoapps/mobile_api/social_facebook/courses/views.py
deleted
100644 → 0
View file @
080b7d7b
"""
Views for courses info API
"""
from
rest_framework
import
generics
,
status
from
rest_framework.response
import
Response
from
courseware.access
import
is_mobile_available_for_user
from
student.models
import
CourseEnrollment
from
lms.djangoapps.mobile_api.social_facebook.courses
import
serializers
from
...users.serializers
import
CourseEnrollmentSerializer
from
...utils
import
mobile_view
from
..utils
import
get_friends_from_facebook
,
get_linked_edx_accounts
,
share_with_facebook_friends
@mobile_view
()
class
CoursesWithFriends
(
generics
.
ListAPIView
):
"""
**Use Case**
API endpoint for retrieving all the courses that a user's friends are in.
Note that only friends that allow their courses to be shared will be included.
**Example request**
GET /api/mobile/v0.5/social/facebook/courses/friends
**Response Values**
See UserCourseEnrollmentsList in lms/djangoapps/mobile_api/users for the structure of the response values.
"""
serializer_class
=
serializers
.
CoursesWithFriendsSerializer
def
list
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
self
.
get_serializer
(
data
=
request
.
GET
)
if
not
serializer
.
is_valid
():
return
Response
(
serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
# Get friends from Facebook
result
=
get_friends_from_facebook
(
serializer
)
if
not
isinstance
(
result
,
list
):
return
result
friends_that_are_edx_users
=
get_linked_edx_accounts
(
result
)
# Filter by sharing preferences
users_with_sharing
=
[
friend
for
friend
in
friends_that_are_edx_users
if
share_with_facebook_friends
(
friend
)
]
# Get unique enrollments
enrollments
=
[]
for
friend
in
users_with_sharing
:
query_set
=
CourseEnrollment
.
objects
.
filter
(
user_id
=
friend
[
'edX_id'
]
)
.
exclude
(
course_id__in
=
[
enrollment
.
course_id
for
enrollment
in
enrollments
])
enrollments
.
extend
(
query_set
)
# Get course objects
courses
=
[
enrollment
for
enrollment
in
enrollments
if
enrollment
.
course
and
is_mobile_available_for_user
(
self
.
request
.
user
,
enrollment
.
course
)
]
serializer
=
CourseEnrollmentSerializer
(
courses
,
context
=
{
'request'
:
request
},
many
=
True
)
return
Response
(
serializer
.
data
)
lms/djangoapps/mobile_api/social_facebook/friends/__init__.py
deleted
100644 → 0
View file @
080b7d7b
"""
Friends API
"""
lms/djangoapps/mobile_api/social_facebook/friends/models.py
deleted
100644 → 0
View file @
080b7d7b
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/social_facebook/friends/serializers.py
deleted
100644 → 0
View file @
080b7d7b
"""
Serializer for Friends API
"""
from
rest_framework
import
serializers
class
FriendsInCourseSerializer
(
serializers
.
Serializer
):
"""
Serializes oauth token for facebook groups request
"""
oauth_token
=
serializers
.
CharField
(
required
=
True
)
lms/djangoapps/mobile_api/social_facebook/friends/tests.py
deleted
100644 → 0
View file @
080b7d7b
This diff is collapsed.
Click to expand it.
lms/djangoapps/mobile_api/social_facebook/friends/urls.py
deleted
100644 → 0
View file @
080b7d7b
"""
URLs for friends API
"""
from
django.conf.urls
import
patterns
,
url
from
django.conf
import
settings
from
.views
import
FriendsInCourse
urlpatterns
=
patterns
(
'mobile_api.social_facebook.friends.views'
,
url
(
r'^course/{}$'
.
format
(
settings
.
COURSE_ID_PATTERN
),
FriendsInCourse
.
as_view
(),
name
=
'friends-in-course'
),
)
lms/djangoapps/mobile_api/social_facebook/friends/views.py
deleted
100644 → 0
View file @
080b7d7b
"""
Views for friends info API
"""
from
rest_framework
import
generics
,
status
from
rest_framework.response
import
Response
from
opaque_keys.edx.keys
import
CourseKey
from
student.models
import
CourseEnrollment
from
...utils
import
mobile_view
from
..utils
import
get_friends_from_facebook
,
get_linked_edx_accounts
,
share_with_facebook_friends
from
lms.djangoapps.mobile_api.social_facebook.friends
import
serializers
@mobile_view
()
class
FriendsInCourse
(
generics
.
ListAPIView
):
"""
**Use Case**
API endpoint that returns all the users friends that are in the course specified.
Note that only friends that allow their courses to be shared will be included.
**Example request**:
GET /api/mobile/v0.5/social/facebook/friends/course/<course_id>
where course_id is in the form of /edX/DemoX/Demo_Course
**Response Values**
{
"friends": [
{
"name": "test",
"id": "12345",
},
...
]
}
"""
serializer_class
=
serializers
.
FriendsInCourseSerializer
def
list
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
self
.
get_serializer
(
data
=
request
.
GET
)
if
not
serializer
.
is_valid
():
return
Response
(
serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
# Get all the user's FB friends
result
=
get_friends_from_facebook
(
serializer
)
if
not
isinstance
(
result
,
list
):
return
result
def
is_member
(
friend
,
course_key
):
"""
Return true if friend is a member of the course specified by the course_key
"""
return
CourseEnrollment
.
objects
.
filter
(
course_id
=
course_key
,
user_id
=
friend
[
'edX_id'
]
)
.
count
()
==
1
# For each friend check if they are a linked edX user
friends_with_edx_users
=
get_linked_edx_accounts
(
result
)
# Filter by sharing preferences and enrollment in course
course_key
=
CourseKey
.
from_string
(
kwargs
[
'course_id'
])
friends_with_sharing_in_course
=
[
{
'id'
:
friend
[
'id'
],
'name'
:
friend
[
'name'
]}
for
friend
in
friends_with_edx_users
if
share_with_facebook_friends
(
friend
)
and
is_member
(
friend
,
course_key
)
]
return
Response
({
'friends'
:
friends_with_sharing_in_course
})
lms/djangoapps/mobile_api/social_facebook/groups/__init__.py
deleted
100644 → 0
View file @
080b7d7b
"""
Groups API
"""
lms/djangoapps/mobile_api/social_facebook/groups/models.py
deleted
100644 → 0
View file @
080b7d7b
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/social_facebook/groups/serializers.py
deleted
100644 → 0
View file @
080b7d7b
"""
Serializer for user API
"""
from
rest_framework
import
serializers
from
django.core.validators
import
RegexValidator
class
GroupSerializer
(
serializers
.
Serializer
):
"""
Serializes facebook groups request
"""
name
=
serializers
.
CharField
(
max_length
=
150
)
description
=
serializers
.
CharField
(
max_length
=
200
,
required
=
False
)
privacy
=
serializers
.
ChoiceField
(
choices
=
[(
"open"
,
"open"
),
(
"closed"
,
"closed"
)],
required
=
False
)
class
GroupsMembersSerializer
(
serializers
.
Serializer
):
"""
Serializes facebook invitations request
"""
member_ids
=
serializers
.
CharField
(
required
=
True
,
validators
=
[
RegexValidator
(
regex
=
r'^([\d]+,?)*$'
,
message
=
'A comma separated list of member ids must be provided'
,
code
=
'member_ids error'
),
]
)
lms/djangoapps/mobile_api/social_facebook/groups/tests.py
deleted
100644 → 0
View file @
080b7d7b
"""
Tests for groups
"""
import
httpretty
from
ddt
import
ddt
,
data
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
courseware.tests.factories
import
UserFactory
from
..test_utils
import
SocialFacebookTestCase
@ddt
class
TestGroups
(
SocialFacebookTestCase
):
"""
Tests for /api/mobile/v0.5/social/facebook/groups/...
"""
def
setUp
(
self
):
super
(
TestGroups
,
self
)
.
setUp
()
self
.
user
=
UserFactory
.
create
()
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
'test'
)
# Group Creation and Deletion Tests
@httpretty.activate
def
test_create_new_open_group
(
self
):
group_id
=
'12345678'
status_code
=
200
self
.
set_facebook_interceptor_for_access_token
()
self
.
set_facebook_interceptor_for_groups
({
'id'
:
group_id
},
status_code
)
url
=
reverse
(
'create-delete-group'
,
kwargs
=
{
'group_id'
:
''
})
response
=
self
.
client
.
post
(
url
,
{
'name'
:
'TheBestGroup'
,
'description'
:
'The group for the best people'
,
'privacy'
:
'open'
}
)
self
.
assertEqual
(
response
.
status_code
,
status_code
)
self
.
assertTrue
(
'id'
in
response
.
data
)
# pylint: disable=E1103
self
.
assertEqual
(
response
.
data
[
'id'
],
group_id
)
# pylint: disable=E1103
@httpretty.activate
def
test_create_new_closed_group
(
self
):
group_id
=
'12345678'
status_code
=
200
self
.
set_facebook_interceptor_for_access_token
()
self
.
set_facebook_interceptor_for_groups
({
'id'
:
group_id
},
status_code
)
# Create new group
url
=
reverse
(
'create-delete-group'
,
kwargs
=
{
'group_id'
:
''
})
response
=
self
.
client
.
post
(
url
,
{
'name'
:
'TheBestGroup'
,
'description'
:
'The group for the best people'
,
'privacy'
:
'closed'
}
)
self
.
assertEqual
(
response
.
status_code
,
status_code
)
self
.
assertTrue
(
'id'
in
response
.
data
)
# pylint: disable=E1103
self
.
assertEqual
(
response
.
data
[
'id'
],
group_id
)
# pylint: disable=E1103
def
test_create_new_group_no_name
(
self
):
url
=
reverse
(
'create-delete-group'
,
kwargs
=
{
'group_id'
:
''
})
response
=
self
.
client
.
post
(
url
,
{})
self
.
assertEqual
(
response
.
status_code
,
400
)
def
test_create_new_group_with_invalid_name
(
self
):
url
=
reverse
(
'create-delete-group'
,
kwargs
=
{
'group_id'
:
''
})
response
=
self
.
client
.
post
(
url
,
{
'invalid_name'
:
'TheBestGroup'
})
self
.
assertEqual
(
response
.
status_code
,
400
)
def
test_create_new_group_with_invalid_privacy
(
self
):
url
=
reverse
(
'create-delete-group'
,
kwargs
=
{
'group_id'
:
''
})
response
=
self
.
client
.
post
(
url
,
{
'name'
:
'TheBestGroup'
,
'privacy'
:
'half_open_half_closed'
}
)
self
.
assertEqual
(
response
.
status_code
,
400
)
@httpretty.activate
def
test_delete_group_that_exists
(
self
):
# Create new group
group_id
=
'12345678'
status_code
=
200
self
.
set_facebook_interceptor_for_access_token
()
self
.
set_facebook_interceptor_for_groups
({
'id'
:
group_id
},
status_code
)
url
=
reverse
(
'create-delete-group'
,
kwargs
=
{
'group_id'
:
''
})
response
=
self
.
client
.
post
(
url
,
{
'name'
:
'TheBestGroup'
,
'description'
:
'The group for the best people'
,
'privacy'
:
'open'
}
)
self
.
assertEqual
(
response
.
status_code
,
status_code
)
self
.
assertTrue
(
'id'
in
response
.
data
)
# pylint: disable=E1103
# delete group
httpretty
.
register_uri
(
httpretty
.
POST
,
'https://graph.facebook.com/{}/{}/groups/{}?access_token=FakeToken&method=delete'
.
format
(
settings
.
FACEBOOK_API_VERSION
,
settings
.
FACEBOOK_APP_ID
,
group_id
),
body
=
'{"success": "true"}'
,
status
=
status_code
)
response
=
self
.
delete_group
(
response
.
data
[
'id'
])
# pylint: disable=E1101
self
.
assertTrue
(
response
.
status_code
,
status_code
)
@httpretty.activate
def
test_delete
(
self
):
group_id
=
'12345678'
status_code
=
400
httpretty
.
register_uri
(
httpretty
.
GET
,
'https://graph.facebook.com/oauth/access_token?client_secret={}&grant_type=client_credentials&client_id={}'
.
format
(
settings
.
FACEBOOK_APP_SECRET
,
settings
.
FACEBOOK_APP_ID
),
body
=
'FakeToken=FakeToken'
,
status
=
200
)
httpretty
.
register_uri
(
httpretty
.
POST
,
'https://graph.facebook.com/{}/{}/groups/{}?access_token=FakeToken&method=delete'
.
format
(
settings
.
FACEBOOK_API_VERSION
,
settings
.
FACEBOOK_APP_ID
,
group_id
),
body
=
'{"error": {"message": "error message"}}'
,
status
=
status_code
)
response
=
self
.
delete_group
(
group_id
)
self
.
assertTrue
(
response
.
status_code
,
status_code
)
# Member addition and Removal tests
@data
(
'1234,,,,5678,,'
,
'this00is00not00a00valid00id'
,
'1234,abc,5678'
,
''
)
def
test_invite_single_member_malformed_member_id
(
self
,
member_id
):
group_id
=
'111111111111111'
response
=
self
.
invite_to_group
(
group_id
,
member_id
)
self
.
assertEqual
(
response
.
status_code
,
400
)
@httpretty.activate
def
test_invite_single_member
(
self
):
group_id
=
'111111111111111'
member_id
=
'44444444444444444'
status_code
=
200
self
.
set_facebook_interceptor_for_access_token
()
self
.
set_facebook_interceptor_for_members
({
'success'
:
'True'
},
status_code
,
group_id
,
member_id
)
response
=
self
.
invite_to_group
(
group_id
,
member_id
)
self
.
assertEqual
(
response
.
status_code
,
status_code
)
self
.
assertTrue
(
'success'
in
response
.
data
[
member_id
])
@httpretty.activate
def
test_invite_multiple_members_successfully
(
self
):
member_ids
=
'222222222222222,333333333333333,44444444444444444'
group_id
=
'111111111111111'
status_code
=
200
self
.
set_facebook_interceptor_for_access_token
()
for
member_id
in
member_ids
.
split
(
','
):
self
.
set_facebook_interceptor_for_members
({
'success'
:
'True'
},
status_code
,
group_id
,
member_id
)
response
=
self
.
invite_to_group
(
group_id
,
member_ids
)
self
.
assertEqual
(
response
.
status_code
,
status_code
)
for
member_id
in
member_ids
.
split
(
','
):
self
.
assertTrue
(
'success'
in
response
.
data
[
member_id
])
@httpretty.activate
def
test_invite_single_member_unsuccessfully
(
self
):
group_id
=
'111111111111111'
member_id
=
'44444444444444444'
status_code
=
400
self
.
set_facebook_interceptor_for_access_token
()
self
.
set_facebook_interceptor_for_members
(
{
'error'
:
{
'message'
:
'error message'
}},
status_code
,
group_id
,
member_id
)
response
=
self
.
invite_to_group
(
group_id
,
member_id
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertTrue
(
'error message'
in
response
.
data
[
member_id
])
@httpretty.activate
def
test_invite_multiple_members_unsuccessfully
(
self
):
member_ids
=
'222222222222222,333333333333333,44444444444444444'
group_id
=
'111111111111111'
status_code
=
400
self
.
set_facebook_interceptor_for_access_token
()
for
member_id
in
member_ids
.
split
(
','
):
self
.
set_facebook_interceptor_for_members
(
{
'error'
:
{
'message'
:
'error message'
}},
status_code
,
group_id
,
member_id
)
response
=
self
.
invite_to_group
(
group_id
,
member_ids
)
self
.
assertEqual
(
response
.
status_code
,
200
)
for
member_id
in
member_ids
.
split
(
','
):
self
.
assertTrue
(
'error message'
in
response
.
data
[
member_id
])
lms/djangoapps/mobile_api/social_facebook/groups/urls.py
deleted
100644 → 0
View file @
080b7d7b
"""
URLs for groups API
"""
from
django.conf.urls
import
patterns
,
url
from
.views
import
Groups
,
GroupsMembers
urlpatterns
=
patterns
(
'mobile_api.social_facebook.groups.views'
,
url
(
r'^(?P<group_id>[\d]*)$'
,
Groups
.
as_view
(),
name
=
'create-delete-group'
),
url
(
r'^(?P<group_id>[\d]+)/member/(?P<member_id>[\d]*,*)$'
,
GroupsMembers
.
as_view
(),
name
=
'add-remove-member'
)
)
lms/djangoapps/mobile_api/social_facebook/groups/views.py
deleted
100644 → 0
View file @
080b7d7b
"""
Views for groups info API
"""
from
rest_framework
import
generics
,
status
,
mixins
from
rest_framework.response
import
Response
from
django.conf
import
settings
import
facebook
from
...utils
import
mobile_view
from
.
import
serializers
@mobile_view
()
class
Groups
(
generics
.
CreateAPIView
,
mixins
.
DestroyModelMixin
):
"""
**Use Case**
An API to Create or Delete course groups.
Note: The Delete is not invoked from the current version of the app
and is used only for testing with facebook dependencies.
**Creation Example request**:
POST /api/mobile/v0.5/social/facebook/groups/
Parameters: name : string,
description : string,
privacy : open/closed
**Creation Response Values**
{"id": group_id}
**Deletion Example request**:
DELETE /api/mobile/v0.5/social/facebook/groups/<group_id>
**Deletion Response Values**
{"success" : "true"}
"""
serializer_class
=
serializers
.
GroupSerializer
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
self
.
get_serializer
(
data
=
request
.
data
)
if
not
serializer
.
is_valid
():
return
Response
(
serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
try
:
app_groups_response
=
facebook_graph_api
()
.
request
(
settings
.
FACEBOOK_API_VERSION
+
'/'
+
settings
.
FACEBOOK_APP_ID
+
"/groups"
,
post_args
=
request
.
POST
.
dict
()
)
return
Response
(
app_groups_response
)
except
facebook
.
GraphAPIError
,
ex
:
return
Response
({
'error'
:
ex
.
result
[
'error'
][
'message'
]},
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
# pylint: disable=unused-argument
"""
Deletes the course group.
"""
try
:
return
Response
(
facebook_graph_api
()
.
request
(
settings
.
FACEBOOK_API_VERSION
+
'/'
+
settings
.
FACEBOOK_APP_ID
+
"/groups/"
+
kwargs
[
'group_id'
],
post_args
=
{
'method'
:
'delete'
}
)
)
except
facebook
.
GraphAPIError
,
ex
:
return
Response
({
'error'
:
ex
.
result
[
'error'
][
'message'
]},
status
=
status
.
HTTP_400_BAD_REQUEST
)
@mobile_view
()
class
GroupsMembers
(
generics
.
CreateAPIView
,
mixins
.
DestroyModelMixin
):
"""
**Use Case**
An API to Invite and Remove members to a group
Note: The Remove is not invoked from the current version
of the app and is used only for testing with facebook dependencies.
**Invite Example request**:
POST /api/mobile/v0.5/social/facebook/groups/<group_id>/member/
Parameters: members : int,int,int...
**Invite Response Values**
{"member_id" : success/error_message}
A response with each member_id and whether or not the member was added successfully.
If the member was not added successfully the Facebook error message is provided.
**Remove Example request**:
DELETE /api/mobile/v0.5/social/facebook/groups/<group_id>/member/<member_id>
**Remove Response Values**
{"success" : "true"}
"""
serializer_class
=
serializers
.
GroupsMembersSerializer
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
self
.
get_serializer
(
data
=
request
.
data
)
if
not
serializer
.
is_valid
():
return
Response
(
serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
graph
=
facebook_graph_api
()
url
=
settings
.
FACEBOOK_API_VERSION
+
'/'
+
kwargs
[
'group_id'
]
+
"/members"
member_ids
=
serializer
.
data
[
'member_ids'
]
.
split
(
','
)
response
=
{}
for
member_id
in
member_ids
:
try
:
if
'success'
in
graph
.
request
(
url
,
post_args
=
{
'member'
:
member_id
}):
response
[
member_id
]
=
'success'
except
facebook
.
GraphAPIError
,
ex
:
response
[
member_id
]
=
ex
.
result
[
'error'
][
'message'
]
return
Response
(
response
,
status
=
status
.
HTTP_200_OK
)
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
# pylint: disable=unused-argument
"""
Deletes the member from the course group.
"""
try
:
return
Response
(
facebook_graph_api
()
.
request
(
settings
.
FACEBOOK_API_VERSION
+
'/'
+
kwargs
[
'group_id'
]
+
"/members"
,
post_args
=
{
'method'
:
'delete'
,
'member'
:
kwargs
[
'member_id'
]}
)
)
except
facebook
.
GraphAPIError
,
ex
:
return
Response
({
'error'
:
ex
.
result
[
'error'
][
'message'
]},
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
facebook_graph_api
():
"""
Returns the result from calling Facebook's Graph API with the app's access token.
"""
return
facebook
.
GraphAPI
(
facebook
.
get_app_access_token
(
settings
.
FACEBOOK_APP_ID
,
settings
.
FACEBOOK_APP_SECRET
))
lms/djangoapps/mobile_api/social_facebook/models.py
deleted
100644 → 0
View file @
080b7d7b
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/social_facebook/preferences/__init__.py
deleted
100644 → 0
View file @
080b7d7b
"""
Users Sharing preferences API
"""
lms/djangoapps/mobile_api/social_facebook/preferences/models.py
deleted
100644 → 0
View file @
080b7d7b
"""
A models.py is required to make this an app (until we move to Django 1.7)
"""
lms/djangoapps/mobile_api/social_facebook/preferences/serializers.py
deleted
100644 → 0
View file @
080b7d7b
"""
Serializer for Share Settings API
"""
from
rest_framework
import
serializers
class
UserSharingSerializar
(
serializers
.
Serializer
):
"""
Serializes user social settings
"""
share_with_facebook_friends
=
serializers
.
BooleanField
(
required
=
True
)
lms/djangoapps/mobile_api/social_facebook/preferences/tests.py
deleted
100644 → 0
View file @
080b7d7b
"""
Tests for users sharing preferences
"""
from
django.core.urlresolvers
import
reverse
from
..test_utils
import
SocialFacebookTestCase
class
StudentProfileViewTest
(
SocialFacebookTestCase
):
""" Tests for the student profile views. """
USERNAME
=
u'bnotions'
PASSWORD
=
u'horse'
EMAIL
=
u'horse@bnotions.com'
FULL_NAME
=
u'bnotions horse'
def
setUp
(
self
):
super
(
StudentProfileViewTest
,
self
)
.
setUp
()
self
.
user_create_and_signin
(
1
)
def
assert_shared_value
(
self
,
response
,
expected_value
=
'True'
):
"""
Tests whether the response is successful and whether the
share_with_facebook_friends value is set to the expected value.
"""
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertTrue
(
'share_with_facebook_friends'
in
response
.
data
)
self
.
assertTrue
(
expected_value
in
response
.
data
[
'share_with_facebook_friends'
])
def
test_set_preferences_to_true
(
self
):
url
=
reverse
(
'preferences'
)
response
=
self
.
client
.
post
(
url
,
{
'share_with_facebook_friends'
:
'True'
})
self
.
assert_shared_value
(
response
)
def
test_set_preferences_to_false
(
self
):
url
=
reverse
(
'preferences'
)
response
=
self
.
client
.
post
(
url
,
{
'share_with_facebook_friends'
:
'False'
})
self
.
assert_shared_value
(
response
,
'False'
)
def
test_set_preferences_no_parameters
(
self
):
# Note that if no value is given it will default to False
url
=
reverse
(
'preferences'
)
response
=
self
.
client
.
post
(
url
,
{})
self
.
assert_shared_value
(
response
,
'False'
)
def
test_set_preferences_invalid_parameters
(
self
):
# Note that if no value is given it will default to False
# also in the case of invalid parameters
url
=
reverse
(
'preferences'
)
response
=
self
.
client
.
post
(
url
,
{
'bad_param'
:
'False'
})
self
.
assert_shared_value
(
response
,
'False'
)
def
test_get_preferences_after_setting_them
(
self
):
url
=
reverse
(
'preferences'
)
for
boolean
in
[
'True'
,
'False'
]:
# Set the preference
response
=
self
.
client
.
post
(
url
,
{
'share_with_facebook_friends'
:
boolean
})
self
.
assert_shared_value
(
response
,
boolean
)
# Get the preference
response
=
self
.
client
.
get
(
url
)
self
.
assert_shared_value
(
response
,
boolean
)
def
test_get_preferences_without_setting_them
(
self
):
url
=
reverse
(
'preferences'
)
# Get the preference
response
=
self
.
client
.
get
(
url
)
self
.
assert_shared_value
(
response
,
'False'
)
lms/djangoapps/mobile_api/social_facebook/preferences/urls.py
deleted
100644 → 0
View file @
080b7d7b
"""
URLs for users sharing preferences
"""
from
django.conf.urls
import
patterns
,
url
from
.views
import
UserSharing
urlpatterns
=
patterns
(
'mobile_api.social_facebook.preferences.views'
,
url
(
r'^preferences/$'
,
UserSharing
.
as_view
(),
name
=
'preferences'
),
)
lms/djangoapps/mobile_api/social_facebook/preferences/views.py
deleted
100644 → 0
View file @
080b7d7b
"""
Views for users sharing preferences
"""
from
rest_framework
import
generics
,
status
from
rest_framework.response
import
Response
from
openedx.core.djangoapps.user_api.preferences.api
import
get_user_preferences
,
set_user_preference
from
...utils
import
mobile_view
from
.
import
serializers
@mobile_view
()
class
UserSharing
(
generics
.
ListCreateAPIView
):
"""
**Use Case**
An API to retrieve or update the users social sharing settings
**GET Example request**:
GET /api/mobile/v0.5/settings/preferences/
**GET Response Values**
{'share_with_facebook_friends': 'True'}
**POST Example request**:
POST /api/mobile/v0.5/settings/preferences/
paramters: share_with_facebook_friends : True
**POST Response Values**
{'share_with_facebook_friends': 'True'}
"""
serializer_class
=
serializers
.
UserSharingSerializar
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
self
.
get_serializer
(
data
=
request
.
data
)
if
serializer
.
is_valid
():
value
=
serializer
.
data
[
'share_with_facebook_friends'
]
set_user_preference
(
request
.
user
,
"share_with_facebook_friends"
,
value
)
return
self
.
get
(
request
,
*
args
,
**
kwargs
)
return
Response
(
serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
preferences
=
get_user_preferences
(
request
.
user
)
response
=
{
'share_with_facebook_friends'
:
preferences
.
get
(
'share_with_facebook_friends'
,
'False'
)}
return
Response
(
response
)
lms/djangoapps/mobile_api/social_facebook/test_utils.py
deleted
100644 → 0
View file @
080b7d7b
"""
Test utils for Facebook functionality
"""
import
httpretty
import
json
from
rest_framework.test
import
APITestCase
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
social.apps.django_app.default.models
import
UserSocialAuth
from
course_modes.models
import
CourseMode
from
student.models
import
CourseEnrollment
from
student.views
import
login_oauth_token
from
openedx.core.djangoapps.user_api.preferences.api
import
get_user_preference
,
set_user_preference
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
courseware.tests.factories
import
UserFactory
class
SocialFacebookTestCase
(
ModuleStoreTestCase
,
APITestCase
):
"""
Base Class for social test cases
"""
USERS
=
{
1
:
{
'USERNAME'
:
"TestUser One"
,
'EMAIL'
:
"test_one@ebnotions.com"
,
'PASSWORD'
:
"edx"
,
'FB_ID'
:
"11111111111111111"
},
2
:
{
'USERNAME'
:
"TestUser Two"
,
'EMAIL'
:
"test_two@ebnotions.com"
,
'PASSWORD'
:
"edx"
,
'FB_ID'
:
"22222222222222222"
},
3
:
{
'USERNAME'
:
"TestUser Three"
,
'EMAIL'
:
"test_three@ebnotions.com"
,
'PASSWORD'
:
"edx"
,
'FB_ID'
:
"33333333333333333"
}
}
BACKEND
=
"facebook"
USER_URL
=
"https://graph.facebook.com/me"
UID_FIELD
=
"id"
_FB_USER_ACCESS_TOKEN
=
'ThisIsAFakeFacebookToken'
users
=
{}
def
setUp
(
self
):
super
(
SocialFacebookTestCase
,
self
)
.
setUp
()
def
set_facebook_interceptor_for_access_token
(
self
):
"""
Facebook interceptor for groups access_token
"""
httpretty
.
register_uri
(
httpretty
.
GET
,
'https://graph.facebook.com/oauth/access_token?client_secret='
+
settings
.
FACEBOOK_APP_SECRET
+
'&grant_type=client_credentials&client_id='
+
settings
.
FACEBOOK_APP_ID
,
body
=
'FakeToken=FakeToken'
,
status
=
200
)
def
set_facebook_interceptor_for_groups
(
self
,
data
,
status
):
"""
Facebook interceptor for groups test
"""
httpretty
.
register_uri
(
httpretty
.
POST
,
'https://graph.facebook.com/'
+
settings
.
FACEBOOK_API_VERSION
+
'/'
+
settings
.
FACEBOOK_APP_ID
+
'/groups'
,
body
=
json
.
dumps
(
data
),
status
=
status
)
def
set_facebook_interceptor_for_members
(
self
,
data
,
status
,
group_id
,
member_id
):
"""
Facebook interceptor for group members tests
"""
httpretty
.
register_uri
(
httpretty
.
POST
,
'https://graph.facebook.com/'
+
settings
.
FACEBOOK_API_VERSION
+
'/'
+
group_id
+
'/members?member='
+
member_id
+
'&access_token=FakeToken'
,
body
=
json
.
dumps
(
data
),
status
=
status
)
def
set_facebook_interceptor_for_friends
(
self
,
data
):
"""
Facebook interceptor for friends tests
"""
httpretty
.
register_uri
(
httpretty
.
GET
,
"https://graph.facebook.com/v2.2/me/friends"
,
body
=
json
.
dumps
(
data
),
status
=
201
)
def
delete_group
(
self
,
group_id
):
"""
Invoke the delete groups view
"""
url
=
reverse
(
'create-delete-group'
,
kwargs
=
{
'group_id'
:
group_id
})
response
=
self
.
client
.
delete
(
url
)
return
response
def
invite_to_group
(
self
,
group_id
,
member_ids
):
"""
Invoke the invite to group view
"""
url
=
reverse
(
'add-remove-member'
,
kwargs
=
{
'group_id'
:
group_id
,
'member_id'
:
''
})
return
self
.
client
.
post
(
url
,
{
'member_ids'
:
member_ids
})
def
remove_from_group
(
self
,
group_id
,
member_id
):
"""
Invoke the remove from group view
"""
url
=
reverse
(
'add-remove-member'
,
kwargs
=
{
'group_id'
:
group_id
,
'member_id'
:
member_id
})
response
=
self
.
client
.
delete
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
def
link_edx_account_to_social
(
self
,
user
,
backend
,
social_uid
):
"""
Register the user to the social auth backend
"""
reverse
(
login_oauth_token
,
kwargs
=
{
"backend"
:
backend
})
UserSocialAuth
.
objects
.
create
(
user
=
user
,
provider
=
backend
,
uid
=
social_uid
)
def
set_sharing_preferences
(
self
,
user
,
boolean_value
):
"""
Sets self.user's share settings to boolean_value
"""
# Note that setting the value to boolean will result in the conversion to the unicode form of the boolean.
set_user_preference
(
user
,
'share_with_facebook_friends'
,
boolean_value
)
self
.
assertEqual
(
get_user_preference
(
user
,
'share_with_facebook_friends'
),
unicode
(
boolean_value
))
def
_change_enrollment
(
self
,
action
,
course_id
=
None
,
email_opt_in
=
None
):
"""
Change the student's enrollment status in a course.
Args:
action (string): The action to perform (either "enroll" or "unenroll")
Keyword Args:
course_id (unicode): If provided, use this course ID. Otherwise, use the
course ID created in the setup for this test.
email_opt_in (unicode): If provided, pass this value along as
an additional GET parameter.
"""
if
course_id
is
None
:
course_id
=
unicode
(
self
.
course
.
id
)
params
=
{
'enrollment_action'
:
action
,
'course_id'
:
course_id
}
if
email_opt_in
:
params
[
'email_opt_in'
]
=
email_opt_in
return
self
.
client
.
post
(
reverse
(
'change_enrollment'
),
params
)
def
user_create_and_signin
(
self
,
user_number
):
"""
Create a user and sign them in
"""
self
.
users
[
user_number
]
=
UserFactory
.
create
(
username
=
self
.
USERS
[
user_number
][
'USERNAME'
],
email
=
self
.
USERS
[
user_number
][
'EMAIL'
],
password
=
self
.
USERS
[
user_number
][
'PASSWORD'
]
)
self
.
client
.
login
(
username
=
self
.
USERS
[
user_number
][
'USERNAME'
],
password
=
self
.
USERS
[
user_number
][
'PASSWORD'
])
def
enroll_in_course
(
self
,
user
,
course
):
"""
Enroll a user in the course
"""
resp
=
self
.
_change_enrollment
(
'enroll'
,
course_id
=
course
.
id
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertTrue
(
CourseEnrollment
.
is_enrolled
(
user
,
course
.
id
))
course_mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
user
,
course
.
id
)
self
.
assertTrue
(
is_active
)
self
.
assertEqual
(
course_mode
,
CourseMode
.
DEFAULT_MODE_SLUG
)
lms/djangoapps/mobile_api/social_facebook/urls.py
deleted
100644 → 0
View file @
080b7d7b
"""
URLs for Social Facebook
"""
from
django.conf.urls
import
patterns
,
url
,
include
urlpatterns
=
patterns
(
''
,
url
(
r'^courses/'
,
include
(
'mobile_api.social_facebook.courses.urls'
)),
url
(
r'^friends/'
,
include
(
'mobile_api.social_facebook.friends.urls'
)),
url
(
r'^groups/'
,
include
(
'mobile_api.social_facebook.groups.urls'
)),
)
lms/djangoapps/mobile_api/social_facebook/utils.py
deleted
100644 → 0
View file @
080b7d7b
"""
Common utility methods and decorators for Social Facebook APIs.
"""
import
json
import
urllib2
import
facebook
from
django.conf
import
settings
from
django.core.exceptions
import
ObjectDoesNotExist
from
rest_framework
import
status
from
rest_framework.response
import
Response
from
social.apps.django_app.default.models
import
UserSocialAuth
from
openedx.core.djangoapps.user_api.models
import
UserPreference
from
student.models
import
User
# TODO
# The pagination strategy needs to be further flushed out.
# What is the default page size for the facebook Graph API? 25? Is the page size a parameter that can be tweaked?
# If a user has a large number of friends, we would be calling the FB API num_friends/page_size times.
#
# However, on the app, we don't plan to display all those friends anyway.
# If we do, for scalability, the endpoints themselves would need to be paginated.
def
get_pagination
(
friends
):
"""
Get paginated data from FaceBook response
"""
data
=
friends
[
'data'
]
while
'paging'
in
friends
and
'next'
in
friends
[
'paging'
]:
response
=
urllib2
.
urlopen
(
friends
[
'paging'
][
'next'
])
friends
=
json
.
loads
(
response
.
read
())
data
=
data
+
friends
[
'data'
]
return
data
def
get_friends_from_facebook
(
serializer
):
"""
Return a list with the result of a facebook /me/friends call
using the oauth_token contained within the serializer object.
If facebook returns an error, return a response object containing
the error message.
"""
try
:
graph
=
facebook
.
GraphAPI
(
serializer
.
data
[
'oauth_token'
])
friends
=
graph
.
request
(
settings
.
FACEBOOK_API_VERSION
+
"/me/friends"
)
return
get_pagination
(
friends
)
except
facebook
.
GraphAPIError
,
ex
:
return
Response
({
'error'
:
ex
.
result
[
'error'
][
'message'
]},
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
get_linked_edx_accounts
(
data
):
"""
Return a list of friends from the input that are edx users with the
additional attributes of edX_id and edX_username
"""
friends_that_are_edx_users
=
[]
for
friend
in
data
:
query_set
=
UserSocialAuth
.
objects
.
filter
(
uid
=
unicode
(
friend
[
'id'
]))
if
query_set
.
count
()
==
1
:
friend
[
'edX_id'
]
=
query_set
[
0
]
.
user_id
friend
[
'edX_username'
]
=
query_set
[
0
]
.
user
.
username
friends_that_are_edx_users
.
append
(
friend
)
return
friends_that_are_edx_users
def
share_with_facebook_friends
(
friend
):
"""
Return true if the user's share_with_facebook_friends preference is set to true.
"""
# Calling UserPreference directly because the requesting user may be different (and not is_staff).
try
:
existing_user
=
User
.
objects
.
get
(
username
=
friend
[
'edX_username'
])
except
ObjectDoesNotExist
:
return
False
return
UserPreference
.
get_value
(
existing_user
,
'share_with_facebook_friends'
)
==
'True'
lms/djangoapps/mobile_api/urls.py
View file @
fa8ca11d
"""
URLs for mobile API
"""
from
django.conf
import
settings
from
django.conf.urls
import
patterns
,
url
,
include
from
.users.views
import
my_user_info
...
...
@@ -13,9 +12,3 @@ urlpatterns = patterns(
url
(
r'^video_outlines/'
,
include
(
'mobile_api.video_outlines.urls'
)),
url
(
r'^course_info/'
,
include
(
'mobile_api.course_info.urls'
)),
)
if
settings
.
FEATURES
[
"ENABLE_MOBILE_SOCIAL_FACEBOOK_FEATURES"
]:
urlpatterns
+=
(
url
(
r'^social/facebook/'
,
include
(
'mobile_api.social_facebook.urls'
)),
url
(
r'^settings/'
,
include
(
'mobile_api.social_facebook.preferences.urls'
)),
)
lms/djangoapps/mobile_api/users/serializers.py
View file @
fa8ca11d
...
...
@@ -77,10 +77,7 @@ class CourseOverviewField(serializers.RelatedField):
request
=
request
,
),
# Note: The following 2 should be deprecated.
'social_urls'
:
{
'facebook'
:
course_overview
.
facebook_url
,
},
# Note: The following should be deprecated.
'latest_updates'
:
{
'video'
:
None
},
...
...
lms/djangoapps/mobile_api/users/tests.py
View file @
fa8ca11d
...
...
@@ -253,23 +253,6 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
)
)
def
test_no_facebook_url
(
self
):
self
.
login_and_enroll
()
response
=
self
.
api_response
()
course_data
=
response
.
data
[
0
][
'course'
]
self
.
assertIsNone
(
course_data
[
'social_urls'
][
'facebook'
])
def
test_facebook_url
(
self
):
self
.
login_and_enroll
()
self
.
course
.
facebook_url
=
"http://facebook.com/test_group_page"
self
.
store
.
update_item
(
self
.
course
,
self
.
user
.
id
)
response
=
self
.
api_response
()
course_data
=
response
.
data
[
0
][
'course'
]
self
.
assertEquals
(
course_data
[
'social_urls'
][
'facebook'
],
self
.
course
.
facebook_url
)
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
"ENABLE_DISCUSSION_SERVICE"
:
True
})
def
test_discussion_url
(
self
):
self
.
login_and_enroll
()
...
...
lms/envs/common.py
View file @
fa8ca11d
...
...
@@ -271,7 +271,6 @@ FEATURES = {
# Expose Mobile REST API. Note that if you use this, you must also set
# ENABLE_OAUTH2_PROVIDER to True
'ENABLE_MOBILE_REST_API'
:
False
,
'ENABLE_MOBILE_SOCIAL_FACEBOOK_FEATURES'
:
False
,
# Enable temporary APIs required for xBlocks on Mobile
'ENABLE_COURSE_BLOCKS_NAVIGATION_API'
:
False
,
...
...
lms/envs/test.py
View file @
fa8ca11d
...
...
@@ -293,7 +293,6 @@ OIDC_COURSE_HANDLER_CACHE_TIMEOUT = 0
########################### External REST APIs #################################
FEATURES
[
'ENABLE_MOBILE_REST_API'
]
=
True
FEATURES
[
'ENABLE_MOBILE_SOCIAL_FACEBOOK_FEATURES'
]
=
True
FEATURES
[
'ENABLE_VIDEO_ABSTRACTION_LAYER_API'
]
=
True
FEATURES
[
'ENABLE_COURSE_BLOCKS_NAVIGATION_API'
]
=
True
...
...
openedx/core/djangoapps/content/course_overviews/migrations/0008_remove_courseoverview_facebook_url.py
0 → 100644
View file @
fa8ca11d
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'course_overviews'
,
'0007_courseoverviewimageconfig'
),
]
operations
=
[
migrations
.
RemoveField
(
model_name
=
'courseoverview'
,
name
=
'facebook_url'
,
),
]
openedx/core/djangoapps/content/course_overviews/models.py
View file @
fa8ca11d
...
...
@@ -66,7 +66,6 @@ class CourseOverview(TimeStampedModel):
# URLs
course_image_url
=
TextField
()
facebook_url
=
TextField
(
null
=
True
)
social_sharing_url
=
TextField
(
null
=
True
)
end_of_course_survey_url
=
TextField
(
null
=
True
)
...
...
@@ -156,7 +155,6 @@ class CourseOverview(TimeStampedModel):
announcement
=
course
.
announcement
,
course_image_url
=
course_image_url
(
course
),
facebook_url
=
course
.
facebook_url
,
social_sharing_url
=
course
.
social_sharing_url
,
certificates_display_behavior
=
course
.
certificates_display_behavior
,
...
...
openedx/core/djangoapps/content/course_overviews/tests.py
View file @
fa8ca11d
...
...
@@ -91,7 +91,6 @@ class CourseOverviewTestCase(ModuleStoreTestCase):
'display_number_with_default'
,
'display_org_with_default'
,
'advertised_start'
,
'facebook_url'
,
'social_sharing_url'
,
'certificates_display_behavior'
,
'certificates_show_before_end'
,
...
...
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