Merge pull request #4915 from edx/flowerhack/redo-third-party

Facebook auth support.
This commit is contained in:
Julia Hansbrough
2014-08-30 02:50:57 -04:00
14 changed files with 302 additions and 145 deletions

View File

@@ -46,7 +46,8 @@ from student.models import (
Registration, UserProfile, PendingNameChange,
PendingEmailChange, CourseEnrollment, unique_id_for_user,
CourseEnrollmentAllowed, UserStanding, LoginFailures,
create_comments_service_user, PasswordHistory, UserSignupSource
create_comments_service_user, PasswordHistory, UserSignupSource,
anonymous_id_for_user
)
from student.forms import PasswordResetFormNoActive
@@ -92,6 +93,9 @@ from util.password_policy_validators import (
from third_party_auth import pipeline, provider
from xmodule.error_module import ErrorDescriptor
import analytics
from eventtracking import tracker
log = logging.getLogger("edx.student")
AUDIT_LOG = logging.getLogger("audit")
@@ -381,6 +385,10 @@ def register_user(request, extra_context=None):
'username': '',
}
# We save this so, later on, we can determine what course motivated a user's signup
# if they actually complete the registration process
request.session['registration_course_id'] = context['course_id']
if extra_context is not None:
context.update(extra_context)
@@ -951,6 +959,31 @@ def login_user(request, error=""): # pylint: disable-msg=too-many-statements,un
if LoginFailures.is_feature_enabled():
LoginFailures.clear_lockout_counter(user)
# Track the user's sign in
if settings.FEATURES.get('SEGMENT_IO_LMS') and hasattr(settings, 'SEGMENT_IO_LMS_KEY'):
tracking_context = tracker.get_tracker().resolve_context()
analytics.identify(anonymous_id_for_user(user, None), {
'email': email,
'username': username,
})
# If the user entered the flow via a specific course page, we track that
registration_course_id = request.session.get('registration_course_id')
analytics.track(
user.id,
"edx.bi.user.account.authenticated",
{
'category': "conversion",
'label': registration_course_id
},
context={
'Google Analytics': {
'clientId': tracking_context.get('client_id')
}
}
)
request.session['registration_course_id'] = None
if user is not None and user.is_active:
try:
# We do not log here, because we have a handler registered
@@ -1398,6 +1431,33 @@ def create_account(request, post_override=None): # pylint: disable-msg=too-many
(user, profile, registration) = ret
dog_stats_api.increment("common.student.account_created")
email = post_vars['email']
# Track the user's registration
if settings.FEATURES.get('SEGMENT_IO_LMS') and hasattr(settings, 'SEGMENT_IO_LMS_KEY'):
tracking_context = tracker.get_tracker().resolve_context()
analytics.identify(anonymous_id_for_user(user, None), {
email: email,
username: username,
})
registration_course_id = request.session.get('registration_course_id')
analytics.track(
user.id,
"edx.bi.user.account.registered",
{
"category": "conversion",
"label": registration_course_id
},
context={
'Google Analytics': {
'clientId': tracking_context.get('client_id')
}
}
)
request.session['registration_course_id'] = None
create_comments_service_user(user)
context = {

View File

@@ -4,7 +4,7 @@ Loaded by Django's settings mechanism. Consequently, this module must not
invoke the Django armature.
"""
from social.backends import google, linkedin
from social.backends import google, linkedin, facebook
_DEFAULT_ICON_CLASS = 'icon-signin'
@@ -150,6 +150,26 @@ class LinkedInOauth2(BaseProvider):
return provider_details.get('fullname')
class FacebookOauth2(BaseProvider):
"""Provider for LinkedIn's Oauth2 auth system."""
BACKEND_CLASS = facebook.FacebookOAuth2
ICON_CLASS = 'icon-facebook'
NAME = 'Facebook'
SETTINGS = {
'SOCIAL_AUTH_FACEBOOK_KEY': None,
'SOCIAL_AUTH_FACEBOOK_SECRET': None,
}
@classmethod
def get_email(cls, provider_details):
return provider_details.get('email')
@classmethod
def get_name(cls, provider_details):
return provider_details.get('fullname')
class Registry(object):
"""Singleton registry of third-party auth providers.

View File

@@ -282,7 +282,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase):
def assert_register_response_before_pipeline_looks_correct(self, response):
"""Asserts a GET of /register not in the pipeline looks correct."""
self.assertEqual(200, response.status_code)
self.assertIn('Sign in with ' + self.PROVIDER_CLASS.NAME, response.content)
self.assertIn('Sign up with ' + self.PROVIDER_CLASS.NAME, response.content)
self.assert_signin_button_looks_functional(response.content, pipeline.AUTH_ENTRY_REGISTER)
def assert_signin_button_looks_functional(self, content, auth_entry):