Skip to content

Commit

Permalink
Fixes #98. Ouath logins now register new users automatically.
Browse files Browse the repository at this point in the history
  • Loading branch information
peta15 committed Nov 13, 2012
1 parent a9f1b25 commit 3e55be4
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 88 deletions.
158 changes: 75 additions & 83 deletions boilerplate/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ def get(self, provider_name):
twitter_helper = twitter.TwitterAuth(self)
user_data = twitter_helper.auth_complete(oauth_token,
oauth_verifier)
logging.info('twitter user_data: ' + str(user_data))
if self.user:
# new association with twitter
user_info = models.User.get_by_id(long(self.user_id))
Expand Down Expand Up @@ -344,13 +345,9 @@ def get(self, provider_name):
else:
self.redirect_to('home')
else:
# Social user does not exists. Need show login and registration forms
twitter_helper.save_association_data(user_data)
message = _('This Twitter account is not associated with any local account. '
'If you already have a %s Account, you have <a href="/login/">sign in here</a> '
'or <a href="/register/">create an account</a>.' % self.app.config.get('app_name'))
self.add_message(message, 'warning')
self.redirect_to('login', continue_url=continue_url) if continue_url else self.redirect_to('login')
uid = str(user_data['user_id'])
email = str(user_data.get('email'))
self.create_account_from_social_provider(provider_name, uid, email, continue_url, user_data)

# github association
elif provider_name == "github":
Expand All @@ -365,7 +362,7 @@ def get(self, provider_name):
# retrieve the access token using the code and auth object
access_token = github_helper.get_access_token(code)
user_data = github_helper.get_user_info(access_token)

logging.info('github user_data: ' + str(user_data))
if self.user:
# user is already logged in so we set a new association with twitter
user_info = models.User.get_by_id(long(self.user_id))
Expand Down Expand Up @@ -400,14 +397,9 @@ def get(self, provider_name):
logVisit.put()
self.redirect_to('home')
else:
# Social user does not exists. Need show login and registration forms!
login_url = '%s/login/' % self.request.host_url
signup_url = '%s/register/' % self.request.host_url
message = _('This Github account is not associated with any local account. '
'If you already have a %s Account, you can <a href=""%s>sign in here</a> '
'or <a href="%s">create an account</a>.' % (self.app.config.get('app_name'), login_url, signup_url))
self.add_message(message,'info')
self.redirect_to('login')
uid = str(user_data['id'])
email = str(user_data.get('email'))
self.create_account_from_social_provider(provider_name, uid, email, continue_url, user_data)
#end github

# facebook association
Expand All @@ -418,6 +410,7 @@ def get(self, provider_name):
access_token = token['access_token']
fb = facebook.GraphAPI(access_token)
user_data = fb.get_object('me')
logging.info('facebook user_data: ' + str(user_data))
if self.user:
# new association with facebook
user_info = models.User.get_by_id(long(self.user_id))
Expand Down Expand Up @@ -459,14 +452,9 @@ def get(self, provider_name):
else:
self.redirect_to('home')
else:
# Social user does not exists. Need show login and registration forms

self.session['facebook']=json.dumps(user_data)
login_url = '%s/login/' % self.request.host_url
signup_url = '%s/register/' % self.request.host_url
message = _('The Facebook account isn\'t associated with any local account. If you already have a Google App Engine Boilerplate Account, you have <a href="%s">sign in here</a> or <a href="%s">Create an account</a>') % (login_url, signup_url)
self.add_message(message,'info')
self.redirect_to('login', continue_url=continue_url) if continue_url else self.redirect_to('login')
uid = str(user_data['id'])
email = str(user_data.get('email'))
self.create_account_from_social_provider(provider_name, uid, email, continue_url, user_data)

# end facebook
# association with linkedin
Expand All @@ -485,6 +473,7 @@ def get(self, provider_name):
user_key = re.search(r'key=(\d+)', u_data.private_url).group(1)
user_data={'first_name':u_data.first_name, 'last_name':u_data.last_name ,'id':user_key}
self.session['linkedin'] = json.dumps(user_data)
logging.info('linkedin user_data: ' + str(user_data))

if self.user:
# new association with linkedin
Expand Down Expand Up @@ -527,13 +516,9 @@ def get(self, provider_name):
else:
self.redirect_to('home')
else:
# Social user does not exists. Need show login and registration forms
self.session['linkedin'] = json.dumps(user_data)
login_url = '%s/login/' % self.request.host_url
signup_url = '%s/register/' % self.request.host_url
message = _('The Linkedin account isn\'t associated with any local account. If you already have a Google App Engine Boilerplate Account, you have <a href="%s">sign in here</a> or <a href="%s">Create an account</a>') % (login_url, signup_url)
self.add_message(message,'info')
self.redirect_to('login', continue_url=continue_url) if continue_url else self.redirect_to('login')
uid = str(user_data['id'])
email = str(user_data.get('email'))
self.create_account_from_social_provider(provider_name, uid, email, continue_url, user_data)

#end linkedin

Expand Down Expand Up @@ -594,63 +579,70 @@ def get(self, provider_name):
else:
self.redirect_to('home')
else:
# Social user does not exist yet so create it with the federated identity provided (uid)
# and create prerequisite user and log the user account in
if models.SocialUser.check_unique_uid(provider_name, uid):
# create user
# Returns a tuple, where first value is BOOL.
# If True ok, If False no new user is created
# Assume provider has already verified email address
# if email is provided so set activated to True
auth_id = "%s:%s" % (provider_name, uid)
if email:
unique_properties = ['email']
user_info = self.auth.store.user_model.create_user(
auth_id, unique_properties, email=email,
activated=True
)
else:
user_info = self.auth.store.user_model.create_user(
auth_id, activated=True
)
if not user_info[0]: #user is a tuple
message = _('The %s account is already in use.' % provider_display_name)
self.add_message(message, 'error')
return self.redirect_to('register')

user = user_info[1]

# create social user and associate with user
social_user = models.SocialUser(
user = user.key,
provider = provider_name,
uid = uid
)
social_user.put()
# authenticate user
self.auth.set_session(self.auth.store.user_to_dict(user), remember=True)
logVisit = models.LogVisit(
user = user.key,
uastring = self.request.user_agent,
ip = self.request.remote_addr,
timestamp = utils.get_date_time()
)
logVisit.put()

message = _('%s association successfully added.' % provider_display_name)
self.add_message(message, 'success')
else:
message = _('This %s account is already in use.' % provider_display_name)
self.add_message(message, 'error')
if continue_url:
self.redirect(continue_url)
else:
self.redirect_to('edit-profile')
self.create_account_from_social_provider(provider_name, uid, email, continue_url)
else:
message = _('This authentication method is not yet implemented.')
self.add_message(message, 'warning')
self.redirect_to('login', continue_url=continue_url) if continue_url else self.redirect_to('login')

def create_account_from_social_provider(self, provider_name, uid, email=None, continue_url=None, user_data=None):
"""Social user does not exist yet so create it with the federated identity provided (uid)
and create prerequisite user and log the user account in
"""
provider_display_name = models.SocialUser.PROVIDERS_INFO[provider_name]['label']
if models.SocialUser.check_unique_uid(provider_name, uid):
# create user
# Returns a tuple, where first value is BOOL.
# If True ok, If False no new user is created
# Assume provider has already verified email address
# if email is provided so set activated to True
auth_id = "%s:%s" % (provider_name, uid)
if email:
unique_properties = ['email']
user_info = self.auth.store.user_model.create_user(
auth_id, unique_properties, email=email,
activated=True
)
else:
user_info = self.auth.store.user_model.create_user(
auth_id, activated=True
)
if not user_info[0]: #user is a tuple
message = _('The account %s is already in use.' % provider_display_name)
self.add_message(message, 'error')
return self.redirect_to('register')

user = user_info[1]

# create social user and associate with user
social_user = models.SocialUser(
user = user.key,
provider = provider_name,
uid = uid,
)
if user_data:
social_user.extra_data = user_data
self.session[provider_name] = json.dumps(user_data) # TODO is this needed?
social_user.put()
# authenticate user
self.auth.set_session(self.auth.store.user_to_dict(user), remember=True)
logVisit = models.LogVisit(
user = user.key,
uastring = self.request.user_agent,
ip = self.request.remote_addr,
timestamp = utils.get_date_time()
)
logVisit.put()

message = _('Welcome! You have been registered as a new user through %s and logged in.' % provider_display_name)
self.add_message(message, 'success')
else:
message = _('This %s account is already in use.' % provider_display_name)
self.add_message(message, 'error')
if continue_url:
self.redirect(continue_url)
else:
self.redirect_to('edit-profile')

class DeleteSocialProviderHandler(BaseHandler):
"""
Expand Down
9 changes: 4 additions & 5 deletions boilerplate/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ def _login_openid(self, provider, uid, email=None):

def test_login_openid_add_association(self):
response = self._login_openid('google', 'http://www.google.com/accounts/123')
self.assert_success_message_in_response(response, 'association successfully added.')
self.assert_success_message_in_response(response, 'Welcome! You have been registered as a new user')
self.assert_user_logged_in()

def test_login_openid_with_email_add_association(self):
response = self._login_openid('google', 'http://www.google.com/accounts/123', '[email protected]')
self.assert_success_message_in_response(response, 'association successfully added.')
self.assert_success_message_in_response(response, 'Welcome! You have been registered as a new user')
self.assert_user_logged_in()
user = models.User.query().get()
self.assertEqual('[email protected]', user.email)
Expand All @@ -146,9 +146,8 @@ def test_login_openid(self):

def test_login_twitter_no_association(self):
response = self._test_login_twitter()
self.assert_warning_message_in_response(response,
"This Twitter account is not associated with any local account.")
self.assert_user_not_logged_in()
self.assert_success_message_in_response(response, "Welcome! You have been registered as a new user")
self.assert_user_logged_in()

def test_login_twitter_add_association(self):
self.register_activate_login_testuser()
Expand Down

0 comments on commit 3e55be4

Please sign in to comment.