This repository has been archived by the owner on Feb 8, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 308
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Barely logged in with Twitter. Barely (#80)
- Loading branch information
1 parent
3448df6
commit a9f40c8
Showing
7 changed files
with
165 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,4 +15,6 @@ | |
./vendor/mock-0.8.0.tar.gz | ||
./vendor/balanced-0.8.18.tar.gz | ||
|
||
./vendor/requests-oauth-0.4.1.tar.gz | ||
|
||
./ |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
username = path['login'] | ||
^L | ||
{% extends templates/base.html %} | ||
|
||
{% block body %} | ||
|
||
<div id="their-voice"> | ||
<h2 class="first">Are you really {{ username }}?</h2> | ||
|
||
<p>Your attempt to lock or unlock this account failed because you’re | ||
logged into GitHub as someone else. Please <a href="https://github.com/logout" | ||
target="_blank">log out of GitHub</a> and <a | ||
href="./">try again</a>.</p> | ||
</div> | ||
|
||
{% end %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
"""Associate a Twitter account with a Gittip account. | ||
|
||
First we do the OAuth dance with Twitter. Once we've authenticated the user | ||
against Twitter, we record them in our social_network_users table. This table | ||
contains information for Twitter users whether or not they are explicit | ||
participants in the Gittip community. | ||
|
||
""" | ||
import requests | ||
from oauth_hook import OAuthHook | ||
from aspen import log, Response, json | ||
from gittip import db | ||
from gittip.networks import twitter, set_as_claimed | ||
from gittip.authentication import User | ||
from urlparse import parse_qs | ||
|
||
# ========================== ^L | ||
|
||
if 'denied' in qs: | ||
request.redirect('/') | ||
|
||
|
||
token = qs['oauth_token'] | ||
secret, action, then = website.oauth_cache.pop(token) | ||
|
||
|
||
oauth_hook = OAuthHook(token, secret, header_auth=True) | ||
response = requests.post( "https://api.twitter.com/oauth/access_token" | ||
, data={"oauth_verifier": qs['oauth_verifier']} | ||
, hooks={'pre_request': oauth_hook} | ||
) | ||
assert response.status_code == 200 | ||
|
||
qs = parse_qs(response.text) | ||
token = qs['oauth_token'][0] | ||
secret = qs['oauth_token_secret'][0] | ||
user_id = qs['user_id'][0] | ||
|
||
|
||
oauth_hook = OAuthHook(token, secret, header_auth=True) | ||
response = requests.get( "https://api.twitter.com/1/users/show.json?user_id=%s" % user_id | ||
, hooks={'pre_request': oauth_hook} | ||
) | ||
user_info = json.loads(response.text) | ||
assert response.status_code == 200 | ||
|
||
|
||
# Load Twitter user info. | ||
|
||
if action not in [u'opt-in', u'lock', u'unlock']: | ||
raise Response(400) | ||
|
||
# Make sure we have a Twitter screen_name. | ||
screen_name = user_info.get('screen_name') | ||
if screen_name is None: | ||
log(u"We got a user_info from Twitter with no screen_name [%s, %s]" | ||
% (action, then)) | ||
raise Response(400) | ||
|
||
# Do something. | ||
log(u"%s wants to %s" % (screen_name, action)) | ||
if action == 'opt-in': # opt in | ||
participant_id, is_claimed, is_locked, balance = twitter.upsert(user_info) | ||
set_as_claimed(participant_id) | ||
user = User.from_id(participant_id) # give them a session | ||
else: # lock or unlock | ||
if then != screen_name: | ||
|
||
# The user could spoof `then' to match their screen_name, but the most | ||
# they can do is lock/unlock their own Twitter account in a convoluted | ||
# way. | ||
|
||
then = u'/on/twitter/%s/lock-fail.html' % then | ||
|
||
else: | ||
|
||
# Associate the Twitter screen_name with a randomly-named, unclaimed | ||
# Gittip participant. | ||
|
||
participant_id, is_claimed, is_locked, balance \ | ||
= twitter.upsert(user_info) | ||
assert participant_id != screen_name, screen_name # sanity check | ||
|
||
db.execute( "UPDATE social_network_users " | ||
"SET is_locked=%s " | ||
"WHERE participant_id=%s" | ||
, (action == 'lock', participant_id) | ||
) | ||
|
||
if then == u'': | ||
then = u'/%s/' % participant_id | ||
if not then.startswith(u'/'): | ||
# Interpret it as a Twitter screen_name. | ||
then = u'/on/twitter/%s/' % then | ||
request.redirect(then) | ||
|
||
# ========================== ^L text/plain |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from urlparse import parse_qs | ||
|
||
import requests | ||
from oauth_hook import OAuthHook | ||
|
||
OAuthHook.consumer_key = website.twitter_consumer_key | ||
OAuthHook.consumer_secret = website.twitter_consumer_secret | ||
|
||
website.oauth_cache = {} | ||
|
||
# ========================== ^L | ||
|
||
oauth_hook = OAuthHook(header_auth=True) | ||
response = requests.post( "https://api.twitter.com/oauth/request_token" | ||
, hooks={'pre_request': oauth_hook} | ||
) | ||
|
||
assert response.status_code == 200, response.status_code # safety check | ||
|
||
qs = parse_qs(response.text) | ||
|
||
token = qs['oauth_token'][0] | ||
secret = qs['oauth_token_secret'][0] | ||
assert qs['oauth_callback_confirmed'][0] == "true" # sanity check | ||
|
||
action = qs.get('action', 'opt-in') | ||
then = qs.get('then', '') | ||
website.oauth_cache[token] = (secret, action, then) | ||
|
||
url = "https://api.twitter.com/oauth/authenticate?oauth_token=%s" | ||
request.redirect(url % token) | ||
# ========================== ^L text/plain |