Permalink
Browse files

Add django-browserid 0.2, requests 0.9.1, certifi 0.0.4

  • Loading branch information...
1 parent 66cca24 commit 483c736b8353b4e02bca4647c6ed414d11b74bd8 @camd camd committed Mar 26, 2012
Showing with 8,351 additions and 0 deletions.
  1. +1 −0 lib/python/certifi/__init__.py
  2. +3,376 −0 lib/python/certifi/cacert.pem
  3. +34 −0 lib/python/certifi/core.py
  4. +2 −0 lib/python/django_browserid/__init__.py
  5. +117 −0 lib/python/django_browserid/auth.py
  6. +131 −0 lib/python/django_browserid/base.py
  7. +8 −0 lib/python/django_browserid/context_processors.py
  8. +8 −0 lib/python/django_browserid/forms.py
  9. +9 −0 lib/python/django_browserid/urls.py
  10. +68 −0 lib/python/django_browserid/views.py
  11. +34 −0 lib/python/requests/__init__.py
  12. +115 −0 lib/python/requests/api.py
  13. +96 −0 lib/python/requests/async.py
  14. +136 −0 lib/python/requests/auth.py
  15. +44 −0 lib/python/requests/defaults.py
  16. +31 −0 lib/python/requests/exceptions.py
  17. +40 −0 lib/python/requests/hooks.py
  18. +708 −0 lib/python/requests/models.py
  19. +3 −0 lib/python/requests/packages/__init__.py
  20. +3 −0 lib/python/requests/packages/oreos/__init__.py
  21. +24 −0 lib/python/requests/packages/oreos/core.py
  22. +770 −0 lib/python/requests/packages/oreos/monkeys.py
  23. +399 −0 lib/python/requests/packages/oreos/structures.py
  24. +48 −0 lib/python/requests/packages/urllib3/__init__.py
  25. +131 −0 lib/python/requests/packages/urllib3/_collections.py
  26. +552 −0 lib/python/requests/packages/urllib3/connectionpool.py
  27. +35 −0 lib/python/requests/packages/urllib3/exceptions.py
  28. +71 −0 lib/python/requests/packages/urllib3/filepost.py
  29. +4 −0 lib/python/requests/packages/urllib3/packages/__init__.py
  30. +61 −0 lib/python/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py
  31. +128 −0 lib/python/requests/packages/urllib3/poolmanager.py
  32. +145 −0 lib/python/requests/packages/urllib3/request.py
  33. +181 −0 lib/python/requests/packages/urllib3/response.py
  34. +288 −0 lib/python/requests/sessions.py
  35. +86 −0 lib/python/requests/status_codes.py
  36. +66 −0 lib/python/requests/structures.py
  37. +398 −0 lib/python/requests/utils.py
@@ -0,0 +1 @@
+from .core import *
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+ceritfi.py
+~~~~~~~~~~
+
+This module returns the installation location of cacert.pem.
+"""
+
+import os
+
+_content = None
+
+
+def where():
+ f = os.path.split(__file__)[0]
+
+ return os.path.join(f, 'cacert.pem')
+
+def content():
+ global _content
+
+ if not _content:
+ # global _content
+
+ with open(where()) as f:
+ _content = f.read()
+
+ return _content
+
+
+if __name__ == '__main__':
+ print where()
@@ -0,0 +1,2 @@
+from django_browserid.auth import BrowserIDBackend
+from django_browserid.base import get_audience, verify
@@ -0,0 +1,117 @@
+import base64
+import hashlib
+import logging
+from warnings import warn
+
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.importlib import import_module
+
+from django_browserid.base import get_audience as base_get_audience, verify
+
+log = logging.getLogger(__name__)
+
+
+def get_audience(*args):
+ warn('Deprecated, please use the standalone function '
+ 'django_browserid.get_audience instead.', DeprecationWarning)
+ return base_get_audience(*args)
+
+
+def default_username_algo(email):
+ # store the username as a base64 encoded sha1 of the email address
+ # this protects against data leakage because usernames are often
+ # treated as public identifiers (so we can't use the email address).
+ username = base64.urlsafe_b64encode(
+ hashlib.sha1(email).digest()).rstrip('=')
+ return username
+
+
+class BrowserIDBackend(object):
+ supports_anonymous_user = False
+ supports_object_permissions = False
+
+ def verify(self, *args):
+ warn('Deprecated, please use the standalone function '
+ 'django_browserid.verify instead.', DeprecationWarning)
+ return verify(*args)
+
+ def filter_users_by_email(self, email):
+ """Return all users matching the specified email."""
+ return User.objects.filter(email=email)
+
+ def create_user(self, email):
+ """Return object for a newly created user account."""
+ username_algo = getattr(settings, 'BROWSERID_USERNAME_ALGO', None)
+ if username_algo is not None:
+ username = username_algo(email)
+ else:
+ username = default_username_algo(email)
+
+ return User.objects.create_user(username, email)
+
+ def authenticate(self, assertion=None, audience=None):
+ """``django.contrib.auth`` compatible authentication method.
+
+ Given a BrowserID assertion and an audience, it attempts to
+ verify them and then extract the email address for the authenticated
+ user.
+
+ An audience should be in the form ``https://example.com`` or
+ ``http://localhost:8001``.
+
+ See django_browserid.base.get_audience()
+ """
+ result = verify(assertion, audience)
+ if result is None:
+ return None
+
+ email = result['email']
+
+ # in the rare case that two user accounts have the same email address,
+ # log and bail. randomly selecting one seems really wrong.
+ users = self.filter_users_by_email(email=email)
+ if len(users) > 1:
+ log.warn('%d users with email address %s.' % (len(users), email))
+ return None
+ if len(users) == 1:
+ return users[0]
+
+ create_user = getattr(settings, 'BROWSERID_CREATE_USER', False)
+ if not create_user:
+ return None
+ elif create_user == True:
+ return self.create_user(email)
+ else:
+ # Find the function to call, call it and throw in the email.
+ return self._load_module(create_user)(email)
+
+ def get_user(self, user_id):
+ try:
+ return User.objects.get(pk=user_id)
+ except User.DoesNotExist:
+ return None
+
+ def _load_module(self, path):
+ """Code to load create user module. Based off django's load_backend"""
+
+ i = path.rfind('.')
+ module, attr = path[:i], path[i + 1:]
+
+ try:
+ mod = import_module(module)
+ except ImportError, e:
+ raise ImproperlyConfigured('Error importing BROWSERID_CREATE_USER'
+ ' function.')
+ except ValueError, e:
+ raise ImproperlyConfigured('Error importing BROWSERID_CREATE_USER'
+ ' function. Is BROWSERID_CREATE_USER a'
+ ' string?')
+
+ try:
+ create_user = getattr(mod, attr)
+ except AttributeError:
+ raise ImproperlyConfigured('Module "%s" does not define a "%s" '
+ 'function.' % (module, attr))
+ return create_user
@@ -0,0 +1,131 @@
+import logging
+import urllib
+from warnings import warn
+try:
+ import json
+except ImportError:
+ import simplejson as json
+
+
+from django.conf import settings
+
+import requests
+
+
+log = logging.getLogger(__name__)
+
+
+DEFAULT_HTTP_TIMEOUT = 5
+DEFAULT_VERIFICATION_URL = 'https://browserid.org/verify'
+OKAY_RESPONSE = 'okay'
+
+
+def get_audience(request):
+ """Uses Django settings to format the audience.
+
+ To use this function, make sure there is either a SITE_URL in
+ your settings.py file or PROTOCOL and DOMAIN.
+
+ Examples using SITE_URL:
+ SITE_URL = 'http://127.0.0.1:8001'
+ SITE_URL = 'https://example.com'
+ SITE_URL = 'http://example.com'
+
+ If you don't have a SITE_URL you can also use these varables:
+ PROTOCOL, DOMAIN, and (optionally) PORT.
+ Example 1:
+ PROTOCOL = 'https://'
+ DOMAIN = 'example.com'
+
+ Example 2:
+ PROTOCOL = 'http://'
+ DOMAIN = '127.0.0.1'
+ PORT = '8001'
+
+ If none are set, we trust the request to populate the audience.
+ This is *not secure*!
+ """
+ site_url = getattr(settings, 'SITE_URL', False)
+
+ # Note audience based on request for developer warnings
+ if request.is_secure():
+ req_proto = 'https://'
+ else:
+ req_proto = 'http://'
+ req_domain = request.get_host()
+
+ # If we don't define it explicitly
+ if not site_url:
+ warn('Using DOMAIN and PROTOCOL to specify your BrowserID audience is '
+ 'deprecated. Please use the SITE_URL setting instead.',
+ DeprecationWarning)
+
+ # DOMAIN is example.com req_domain is example.com:8001
+ domain = getattr(settings, 'DOMAIN', req_domain.split(':')[0])
+ protocol = getattr(settings, 'PROTOCOL', req_proto)
+
+ standards = {'https://': 443, 'http://': 80}
+ if ':' in req_domain:
+ req_port = req_domain.split(':')[1]
+ else:
+ req_port = None
+ port = getattr(settings, 'PORT', req_port or standards[protocol])
+ if port == standards[protocol]:
+ site_url = ''.join(map(str, (protocol, domain)))
+ else:
+ site_url = ''.join(map(str, (protocol, domain, ':', port)))
+
+ req_url = "%s%s" % (req_proto, req_domain)
+ if site_url != "%s%s" % (req_proto, req_domain):
+ log.warning('Misconfigured SITE_URL? settings has [%s], but '
+ 'actual request was [%s] BrowserID may fail on '
+ 'audience' % (site_url, req_url))
+ return site_url
+
+
+def _verify_http_request(url, qs):
+ parameters = {
+ 'data': qs,
+ 'proxies': getattr(settings, 'BROWSERID_PROXY_INFO', None),
+ 'verify': not getattr(settings, 'BROWSERID_DISABLE_CERT_CHECK', False),
+ 'headers': {'Content-type': 'application/x-www-form-urlencoded'},
+ 'params': {
+ 'timeout': getattr(settings, 'BROWSERID_HTTP_TIMEOUT',
+ DEFAULT_HTTP_TIMEOUT)
+ }
+ }
+
+ if parameters['verify']:
+ parameters['verify'] = getattr(settings, 'BROWSERID_CACERT_FILE', True)
+
+ r = requests.post(url, **parameters)
+
+ try:
+ rv = json.loads(r.content)
+ except ValueError:
+ log.debug('Failed to decode JSON. Resp: %s, Content: %s' %
+ (r.status_code, r.content))
+ return dict(status='failure')
+
+ return rv
+
+
+def verify(assertion, audience):
+ """Verify assertion using an external verification service."""
+ verify_url = getattr(settings, 'BROWSERID_VERIFICATION_URL',
+ DEFAULT_VERIFICATION_URL)
+
+ log.info("Verification URL: %s" % verify_url)
+
+ result = _verify_http_request(verify_url, urllib.urlencode({
+ 'assertion': assertion,
+ 'audience': audience
+ }))
+
+ if result['status'] == OKAY_RESPONSE:
+ return result
+
+ log.error('BrowserID verification failure. Response: %r '
+ 'Audience: %r' % (result, audience))
+ log.error("BID assert: %r" % assertion)
+ return False
@@ -0,0 +1,8 @@
+from django_browserid.forms import BrowserIDForm
+
+
+def browserid_form(request):
+ """
+ A context processor that adds a BrowserID form to the request
+ """
+ return {'browserid_form': BrowserIDForm()}
@@ -0,0 +1,8 @@
+from django import forms
+
+
+class BrowserIDForm(forms.Form):
+ assertion = forms.CharField(widget=forms.HiddenInput())
+
+ class Media:
+ js = ('browserid/browserid.js', 'https://browserid.org/include.js')
@@ -0,0 +1,9 @@
+from django.conf.urls.defaults import patterns, url
+
+from django_browserid.views import Verify
+
+
+urlpatterns = patterns('',
+ url('^browserid/verify/', Verify.as_view(),
+ name='browserid_verify')
+)
@@ -0,0 +1,68 @@
+from django.conf import settings
+from django.contrib import auth
+from django.core.exceptions import ImproperlyConfigured
+from django.shortcuts import redirect
+from django.views.generic.edit import BaseFormView
+
+from django_browserid.forms import BrowserIDForm
+from django_browserid.base import get_audience
+
+
+class Verify(BaseFormView):
+ form_class = BrowserIDForm
+ failure_url = getattr(settings, 'LOGIN_REDIRECT_URL_FAILURE', '/')
+ success_url = getattr(settings, 'LOGIN_REDIRECT_URL', '/')
+
+ def login_success(self):
+ """Handle a successful login. Use this to perform complex redirects
+ post-login.
+ """
+ auth.login(self.request, self.user)
+ redirect_field_name = self.kwargs.get('redirect_field_name',
+ auth.REDIRECT_FIELD_NAME)
+ redirect_to = self.request.REQUEST.get(redirect_field_name, None)
+
+ if redirect_to is not None:
+ return redirect(redirect_to)
+ else:
+ return redirect(self.get_success_url())
+
+ def login_failure(self):
+ """Handle a failed login. Use this to perform complex redirects
+ post-login.
+ """
+ return redirect(self.get_failure_url())
+
+ def form_valid(self, form):
+ """Handles the return post request from the browserID form and puts
+ interesting variables into the class. If everything checks out, then
+ we call handle_user to decide how to handle a valid user
+ """
+ self.assertion = form.cleaned_data['assertion']
+ self.audience = get_audience(self.request)
+ self.user = auth.authenticate(
+ assertion=self.assertion,
+ audience=self.audience)
+
+ if self.user and self.user.is_active:
+ return self.login_success()
+
+ return self.login_failure()
+
+ def form_invalid(self, *args, **kwargs):
+ return self.login_failure()
+
+ def get(self, *args, **kwargs):
+ return redirect(self.get_failure_url())
+
+ def get_failure_url(self):
+ """
+ This is just the django version of get_success_url
+ https://github.com/django/django/blob/master/django/views/generic/edit.py#L51
+ """
+ if self.failure_url:
+ url = self.failure_url
+ else:
+ raise ImproperlyConfigured(
+ "No URL to redirect to. Provide a failure_url.")
+ return url
Oops, something went wrong.

0 comments on commit 483c736

Please sign in to comment.