Commit 017e8975 authored by root's avatar root

use pip

parent 086410f9
......@@ -116,7 +116,6 @@ MIDDLEWARE_CLASSES = (
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
'edumanage.middleware.WrongBackendExceptionMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
......
from django.core.urlresolvers import reverse
from django.conf import settings
from social_auth.exceptions import WrongBackend
class WrongBackendExceptionMiddleware(object):
def process_exception(self, request, exception):
# Get the exception info now, in case another exception is thrown later.
if isinstance(exception, WrongBackend):
return self.handle_404(request, exception)
from django.core.urlresolvers import RegexURLResolver
def handle_404(self, request, exception):
if settings.DEBUG:
from django.views import debug
return debug.technical_404_response(request, exception)
else:
callback, param_dict = resolver(request).resolve404()
return callback(request, **param_dict)
from django.core.urlresolvers import RegexURLResolver
def resolver(request):
"""
Returns a RegexURLResolver for the request's urlconf.
......
Django==1.4.5
MySQL-python==1.2.3
PyJWT==0.2.1
South==1.0
apt-xapian-index==0.45
argparse==1.2.1
chardet==2.0.1
django-registration==1.0
django-tinymce==1.5.3
gevent==0.13.6
httplib2==0.9
ipaddr==2.1.11
lxml==3.4.0
lxml==2.3.2
oauth2==1.5.211
oauthlib==0.6.3
oauthlib==0.7.1
pexpect==2.4
pycrypto==2.6
python-apt==0.8.8.2
python-openid==2.2.5
requests==2.4.1
python-social-auth==0.2.1
requests==2.4.3
requests-oauthlib==0.4.2
six==1.8.0
wsgiref==0.1.2
python-social-auth==0.2.1
"""
Django-social-auth application, allows OpenId or OAuth user
registration/authentication just adding a few configurations.
"""
version = (0, 7, 18)
__version__ = '.'.join(map(str, version))
"""Admin settings"""
from social_auth.utils import setting
if setting('SOCIAL_AUTH_MODELS') in (None, 'social_auth.db.django_models'):
from django.contrib import admin
from social_auth.models import UserSocialAuth, Nonce, Association
class UserSocialAuthOption(admin.ModelAdmin):
"""Social Auth user options"""
list_display = ('id', 'user', 'provider', 'uid')
search_fields = ('user__first_name', 'user__last_name', 'user__email',
'user__username')
list_filter = ('provider',)
raw_id_fields = ('user',)
list_select_related = True
class NonceOption(admin.ModelAdmin):
"""Nonce options"""
list_display = ('id', 'server_url', 'timestamp', 'salt')
search_fields = ('server_url',)
class AssociationOption(admin.ModelAdmin):
"""Association options"""
list_display = ('id', 'server_url', 'assoc_type')
list_filter = ('assoc_type',)
search_fields = ('server_url',)
admin.site.register(UserSocialAuth, UserSocialAuthOption)
admin.site.register(Nonce, NonceOption)
admin.site.register(Association, AssociationOption)
This diff is collapsed.
"""
BrowserID support
"""
import time
from datetime import datetime
from urllib import urlencode
from django.contrib.auth import authenticate
from django.utils import simplejson
from social_auth.backends import SocialAuthBackend, BaseAuth, USERNAME
from social_auth.utils import log, setting, dsa_urlopen
from social_auth.exceptions import AuthFailed, AuthMissingParameter
# BrowserID verification server
BROWSER_ID_SERVER = 'https://verifier.login.persona.org/verify'
class BrowserIDBackend(SocialAuthBackend):
"""BrowserID authentication backend"""
name = 'browserid'
def get_user_id(self, details, response):
"""Use BrowserID email as ID"""
return details['email']
def get_user_details(self, response):
"""Return user details, BrowserID only provides Email."""
# {'status': 'okay',
# 'audience': 'localhost:8000',
# 'expires': 1328983575529,
# 'email': 'name@server.com',
# 'issuer': 'login.persona.org'}
email = response['email']
return {USERNAME: email.split('@', 1)[0],
'email': email,
'fullname': '',
'first_name': '',
'last_name': ''}
def extra_data(self, user, uid, response, details):
"""Return users extra data"""
return {
'audience': response['audience'],
'issuer': response['issuer']
}
# Auth classes
class BrowserIDAuth(BaseAuth):
"""BrowserID authentication"""
AUTH_BACKEND = BrowserIDBackend
def auth_complete(self, *args, **kwargs):
"""Completes loging process, must return user instance"""
if not 'assertion' in self.data:
raise AuthMissingParameter(self, 'assertion')
data = urlencode({
'assertion': self.data['assertion'],
'audience': self.request.get_host()
})
try:
response = simplejson.load(dsa_urlopen(BROWSER_ID_SERVER,
data=data))
except ValueError:
log('error', 'Could not load user data from BrowserID.',
exc_info=True)
else:
if response.get('status') == 'failure':
log('debug', 'Authentication failed.')
raise AuthFailed(self)
kwargs.update({
'auth': self,
'response': response,
self.AUTH_BACKEND.name: True
})
return authenticate(*args, **kwargs)
# Backend definition
BACKENDS = {
'browserid': BrowserIDAuth
}
"""
settings.py should include the following:
ANGEL_CLIENT_ID = '...'
ANGEL_CLIENT_SECRET = '...'
Optional scope to include 'email' and/or 'messages' separated by space:
ANGEL_AUTH_EXTRA_ARGUMENTS = {'scope': 'email messages'}
More information on scope can be found at https://angel.co/api/oauth/faq
"""
from urllib import urlencode
from django.utils import simplejson
from social_auth.backends import BaseOAuth2, OAuthBackend, USERNAME
from social_auth.utils import dsa_urlopen
ANGEL_SERVER = 'angel.co'
ANGEL_AUTHORIZATION_URL = 'https://angel.co/api/oauth/authorize/'
ANGEL_ACCESS_TOKEN_URL = 'https://angel.co/api/oauth/token/'
ANGEL_CHECK_AUTH = 'https://api.angel.co/1/me/'
class AngelBackend(OAuthBackend):
name = 'angel'
def get_user_id(self, details, response):
return response['id']
def get_user_details(self, response):
"""Return user details from Angel account"""
username = response['angellist_url'].split('/')[-1]
first_name = response['name'].split(' ')[0]
last_name = response['name'].split(' ')[-1]
email = response['email']
return {
USERNAME: username,
'first_name': first_name,
'last_name': last_name,
'email': email,
}
class AngelAuth(BaseOAuth2):
"""Angel OAuth mechanism"""
AUTHORIZATION_URL = ANGEL_AUTHORIZATION_URL
ACCESS_TOKEN_URL = ANGEL_ACCESS_TOKEN_URL
AUTH_BACKEND = AngelBackend
SETTINGS_KEY_NAME = 'ANGEL_CLIENT_ID'
SETTINGS_SECRET_NAME = 'ANGEL_CLIENT_SECRET'
REDIRECT_STATE = False
STATE_PARAMETER = False
def user_data(self, access_token, *args, **kwargs):
"""Loads user data from service"""
params = {'access_token': access_token}
url = ANGEL_CHECK_AUTH + '?' + urlencode(params)
try:
return simplejson.load(dsa_urlopen(url))
except ValueError:
return None
# Backend definition
BACKENDS = {
'angel': AngelAuth,
}
"""
Behance OAuth2 support.
This contribution adds support for the Behance OAuth service. The settings
BEHANCE_CLIENT_ID and BEHANCE_CLIENT_SECRET must be defined with the values
given by Behance application registration process.
Extended permissions are supported by defining BEHANCE_EXTENDED_PERMISSIONS
setting, it must be a list of values to request.
By default username and access_token are stored in extra_data field.
"""
from social_auth.backends import BaseOAuth2, OAuthBackend, USERNAME
# Behance configuration
BEHANCE_AUTHORIZATION_URL = 'https://www.behance.net/v2/oauth/authenticate'
BEHANCE_ACCESS_TOKEN_URL = 'https://www.behance.net/v2/oauth/token'
class BehanceBackend(OAuthBackend):
"""Behance OAuth authentication backend"""
name = 'behance'
# Default extra data to store (in addition to access_token)
EXTRA_DATA = [
('username', 'username'),
]
def get_user_id(self, details, response):
return response['user']['id']
def get_user_details(self, response):
"""Return user details from Behance account"""
user = response['user']
return {
USERNAME: user['username'],
'last_name': user['last_name'],
'first_name': user['first_name'],
'fullname': user['display_name'],
'email': '',
}
def extra_data(self, user, uid, response, details):
# Pull up the embedded user attributes so they can be found as extra
# data. See the example token response for possible attributes:
# http://www.behance.net/dev/authentication#step-by-step
all_data = dict((name, value) for name, value in response.iteritems())
all_data.update(response['user'])
return super(BehanceBackend, self).extra_data(user, uid, all_data,
details)
class BehanceAuth(BaseOAuth2):
"""Behance OAuth2 mechanism"""
AUTHORIZATION_URL = BEHANCE_AUTHORIZATION_URL
ACCESS_TOKEN_URL = BEHANCE_ACCESS_TOKEN_URL
AUTH_BACKEND = BehanceBackend
SETTINGS_KEY_NAME = 'BEHANCE_CLIENT_ID'
SETTINGS_SECRET_NAME = 'BEHANCE_CLIENT_SECRET'
SCOPE_SEPARATOR = '|'
### Look at http://www.behance.net/dev/authentication#scopes
SCOPE_VAR_NAME = 'BEHANCE_EXTENDED_PERMISSIONS'
# Backend definition
BACKENDS = {
'behance': BehanceAuth
}
"""
Bitbucket OAuth support.
This adds support for Bitbucket OAuth service. An application must
be registered first on Bitbucket and the settings BITBUCKET_CONSUMER_KEY
and BITBUCKET_CONSUMER_SECRET must be defined with the corresponding
values.
By default username, email, token expiration time, first name and last name are
stored in extra_data field, check OAuthBackend class for details on how to
extend it.
"""
from django.utils import simplejson
from social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME
from social_auth.utils import setting, dsa_urlopen
# Bitbucket configuration
BITBUCKET_SERVER = 'bitbucket.org/api/1.0'
BITBUCKET_REQUEST_TOKEN_URL = 'https://%s/oauth/request_token' % \
BITBUCKET_SERVER
BITBUCKET_ACCESS_TOKEN_URL = 'https://%s/oauth/access_token' % BITBUCKET_SERVER
BITBUCKET_AUTHORIZATION_URL = 'https://%s/oauth/authenticate' % \
BITBUCKET_SERVER
BITBUCKET_EMAIL_DATA_URL = 'https://%s/emails/' % BITBUCKET_SERVER
BITBUCKET_USER_DATA_URL = 'https://%s/users/' % BITBUCKET_SERVER
class BitbucketBackend(OAuthBackend):
"""Bitbucket OAuth authentication backend"""
name = 'bitbucket'
EXTRA_DATA = [
('username', 'username'),
('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')),
('email', 'email'),
('first_name', 'first_name'),
('last_name', 'last_name')
]
def get_user_details(self, response):
"""Return user details from Bitbucket account"""
return {USERNAME: response.get('username'),
'email': response.get('email'),
'fullname': ' '.join((response.get('first_name'),
response.get('last_name'))),
'first_name': response.get('first_name'),
'last_name': response.get('last_name')}
def get_user_id(self, details, response):
"""Return the user id, Bitbucket only provides username as a unique
identifier"""
return response['username']
@classmethod
def tokens(cls, instance):
"""Return the tokens needed to authenticate the access to any API the
service might provide. Bitbucket uses a pair of OAuthToken consisting
on a oauth_token and oauth_token_secret.
instance must be a UserSocialAuth instance.
"""
token = super(BitbucketBackend, cls).tokens(instance)
if token and 'access_token' in token:
token = dict(tok.split('=')
for tok in token['access_token'].split('&'))
return token
class BitbucketAuth(ConsumerBasedOAuth):
"""Bitbucket OAuth authentication mechanism"""
AUTHORIZATION_URL = BITBUCKET_AUTHORIZATION_URL
REQUEST_TOKEN_URL = BITBUCKET_REQUEST_TOKEN_URL
ACCESS_TOKEN_URL = BITBUCKET_ACCESS_TOKEN_URL
AUTH_BACKEND = BitbucketBackend
SETTINGS_KEY_NAME = 'BITBUCKET_CONSUMER_KEY'
SETTINGS_SECRET_NAME = 'BITBUCKET_CONSUMER_SECRET'
def user_data(self, access_token):
"""Return user data provided"""
# Bitbucket has a bit of an indirect route to obtain user data from an
# authenticated query: First obtain the user's email via an
# authenticated GET
url = BITBUCKET_EMAIL_DATA_URL
request = self.oauth_request(access_token, url)
response = self.fetch_response(request)
try:
# Then retrieve the user's primary email address or the top email
email_addresses = simplejson.loads(response)
for email_address in reversed(email_addresses):
if email_address['active']:
email = email_address['email']
if email_address['primary']:
break
# Then return the user data using a normal GET with the
# BITBUCKET_USER_DATA_URL and the user's email
response = dsa_urlopen(BITBUCKET_USER_DATA_URL + email)
user_details = simplejson.load(response)['user']
user_details['email'] = email
return user_details
except ValueError:
return None
return None
# Backend definition
BACKENDS = {
'bitbucket': BitbucketAuth,
}
"""
Dailymotion OAuth2 support.
This adds support for Dailymotion OAuth service. An application must
be registered first on dailymotion and the settings DAILYMOTION_CONSUMER_KEY
and DAILYMOTION_CONSUMER_SECRET must be defined with the corresponding
values.
User screen name is used to generate username.
By default account id is stored in extra_data field, check OAuthBackend
class for details on how to extend it.
"""
from urllib2 import HTTPError
from django.utils import simplejson
from social_auth.utils import dsa_urlopen
from social_auth.backends import USERNAME
from social_auth.backends import BaseOAuth2
from social_auth.backends import SocialAuthBackend
from social_auth.exceptions import AuthCanceled
# Dailymotion configuration
DAILYMOTION_SERVER = 'api.dailymotion.com'
DAILYMOTION_REQUEST_TOKEN_URL = 'https://%s/oauth/token' % DAILYMOTION_SERVER
DAILYMOTION_ACCESS_TOKEN_URL = 'https://%s/oauth/token' % DAILYMOTION_SERVER
# Note: oauth/authorize forces the user to authorize every time.
# oauth/authenticate uses their previous selection, barring revocation.
DAILYMOTION_AUTHORIZATION_URL = 'https://%s/oauth/authorize' % \
DAILYMOTION_SERVER
DAILYMOTION_CHECK_AUTH = 'https://%s/1.1/account/verify_credentials.json' % \
DAILYMOTION_SERVER
DAILYMOTION_CHECK_AUTH = 'https://%s/me/?access_token=' % DAILYMOTION_SERVER
class DailymotionBackend(SocialAuthBackend):
"""Dailymotion OAuth authentication backend"""
name = 'dailymotion'
EXTRA_DATA = [('id', 'id')]
def get_user_id(self, details, response):
"""Use dailymotion username as unique id"""
return details[USERNAME]
def get_user_details(self, response):
return {USERNAME: response['screenname']}
class DailymotionAuth(BaseOAuth2):
"""Dailymotion OAuth2 authentication mechanism"""
AUTHORIZATION_URL = DAILYMOTION_AUTHORIZATION_URL
REQUEST_TOKEN_URL = DAILYMOTION_REQUEST_TOKEN_URL
ACCESS_TOKEN_URL = DAILYMOTION_ACCESS_TOKEN_URL
AUTH_BACKEND = DailymotionBackend
SETTINGS_KEY_NAME = 'DAILYMOTION_OAUTH2_KEY'
SETTINGS_SECRET_NAME = 'DAILYMOTION_OAUTH2_SECRET'
def user_data(self, access_token, *args, **kwargs):
"""Return user data provided"""
try:
data = dsa_urlopen(DAILYMOTION_SERVER + access_token).read()
return simplejson.loads(data)
except (ValueError, HTTPError):
return None
def auth_complete(self, *args, **kwargs):
"""Completes login process, must return user instance"""
if 'denied' in self.data:
raise AuthCanceled(self)
else:
return super(DailymotionAuth, self).auth_complete(*args, **kwargs)
def oauth_request(self, token, url, extra_params=None):
extra_params = extra_params or {}
return extra_params
# Backend definition
BACKENDS = {
'dailymotion': DailymotionAuth,
}
from django.utils import simplejson
from social_auth.backends import BaseOAuth2, OAuthBackend, USERNAME
from social_auth.utils import dsa_urlopen, backend_setting
from social_auth.utils import setting
from urllib import urlencode
DISQUS_SERVER = 'disqus.com'
DISQUS_AUTHORIZATION_URL = 'https://disqus.com/api/oauth/2.0/authorize/'
DISQUS_ACCESS_TOKEN_URL = 'https://disqus.com/api/oauth/2.0/access_token/'
DISQUS_CHECK_AUTH = 'https://disqus.com/api/3.0/users/details.json'
class DisqusBackend(OAuthBackend):
name = 'disqus'
EXTRA_DATA = [
('avatar', 'avatar'),
('connections', 'connections'),
('user_id', 'user_id'),
('email', 'email'),
('email_hash', 'emailHash'),
('expires', setting('SOCIAL_AUTH_EXPIRATION', 'expires')),
('location', 'location'),
('meta', 'response'),
('name', 'name'),
('username', 'username'),
]
def get_user_id(self, details, response):
return response['response']['id']
def get_user_details(self, response):
"""Return user details from Disqus account"""
rr = response.get('response', {})
return {
USERNAME: rr.get('username', ''),
'user_id': response.get('user_id', ''),
'email': rr.get('email', ''),
'name': rr.get('name', ''),
}
def extra_data(self, user, uid, response, details):
meta_response = dict(response, **response.get('response', {}))
return super(DisqusBackend, self).extra_data(user, uid, meta_response, details)
class DisqusAuth(BaseOAuth2):
"""Disqus OAuth mechanism"""
AUTHORIZATION_URL = DISQUS_AUTHORIZATION_URL
ACCESS_TOKEN_URL = DISQUS_ACCESS_TOKEN_URL
AUTH_BACKEND = DisqusBackend
SETTINGS_KEY_NAME = 'DISQUS_CLIENT_ID'
SETTINGS_SECRET_NAME = 'DISQUS_CLIENT_SECRET'
def user_data(self, access_token, *args, **kwargs):
"""Loads user data from service"""
params = {
'access_token': access_token,
'api_secret': backend_setting(self, self.SETTINGS_SECRET_NAME),
}
url = DISQUS_CHECK_AUTH + '?' + urlencode(params)
try:
return simplejson.load(dsa_urlopen(url))
except ValueError:
return None
# Backend definition
BACKENDS = {
'disqus': DisqusAuth,
}
"""
Douban OAuth support.
This adds support for Douban OAuth service. An application must
be registered first on douban.com and the settings DOUBAN_CONSUMER_KEY
and DOUBAN_CONSUMER_SECRET must be defined with they corresponding
values.
By default account id is stored in extra_data field, check OAuthBackend
class for details on how to extend it.
"""
from urllib2 import Request
from django.utils import simplejson
from social_auth.utils import dsa_urlopen
from social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME, \
BaseOAuth2
from social_auth.exceptions import AuthCanceled
DOUBAN_SERVER = 'www.douban.com'
DOUBAN_REQUEST_TOKEN_URL = 'http://%s/service/auth/request_token' % \
DOUBAN_SERVER
DOUBAN_ACCESS_TOKEN_URL = 'http://%s/service/auth/access_token' % \
DOUBAN_SERVER
DOUBAN_AUTHORIZATION_URL = 'http://%s/service/auth/authorize' % \
DOUBAN_SERVER
class DoubanBackend(OAuthBackend):
"""Douban OAuth authentication backend"""
name = 'douban'
EXTRA_DATA = [('id', 'id')]
def get_user_id(self, details, response):
return response['db:uid']['$t']
def get_user_details(self, response):
"""Return user details from Douban"""
return {USERNAME: response["db:uid"]["$t"],
'email': ''}
class DoubanAuth(ConsumerBasedOAuth):
"""Douban OAuth authentication mechanism"""
AUTHORIZATION_URL = DOUBAN_AUTHORIZATION_URL
REQUEST_TOKEN_URL = DOUBAN_REQUEST_TOKEN_URL
ACCESS_TOKEN_URL = DOUBAN_ACCESS_TOKEN_URL
AUTH_BACKEND = DoubanBackend
SETTINGS_KEY_NAME = 'DOUBAN_CONSUMER_KEY'
SETTINGS_SECRET_NAME = 'DOUBAN_CONSUMER_SECRET'
def user_data(self, access_token, *args, **kwargs):
"""Return user data provided"""
url = 'http://api.douban.com/people/%40me?&alt=json'
request = self.oauth_request(access_token, url)
json = self.fetch_response(request)
try:
return simplejson.loads(json)
except ValueError:
return None
def auth_complete(self, *args, **kwargs):
"""Completes login process, must return user instance"""
if 'denied' in self.data:
raise AuthCanceled(self)
else:
return super(DoubanAuth, self).auth_complete(*args, **kwargs)
class DoubanBackend2(OAuthBackend):
"""Douban OAuth authentication backend"""
name = 'douban2'
EXTRA_DATA = [('id', 'id'),
('uid', 'username'),
('refresh_token', 'refresh_token'),
]
def get_user_id(self, details, response):
return response['id']
def get_user_details(self, response):
"""Return user details from Douban"""
return {USERNAME: response.get('uid', ''),
'fullname': response.get('name', ''),
'email': ''}