1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
"""
Utility code for the Django example consumer and server.
"""
from urllib.parse import urljoin
from django.db import connection
from django.template.context import RequestContext
from django.template import loader
from django import http
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse as reverseURL
from django.shortcuts import render_to_response
from django.conf import settings
from openid.store.filestore import FileOpenIDStore
from openid.store import sqlstore
from openid.yadis.constants import YADIS_CONTENT_TYPE
def getOpenIDStore(filestore_path, table_prefix):
"""
Returns an OpenID association store object based on the database
engine chosen for this Django application.
* If no database engine is chosen, a filesystem-based store will
be used whose path is filestore_path.
* If a database engine is chosen, a store object for that database
type will be returned.
* If the chosen engine is not supported by the OpenID library,
raise ImproperlyConfigured.
* If a database store is used, this will create the tables
necessary to use it. The table names will be prefixed with
table_prefix. DO NOT use the same table prefix for both an
OpenID consumer and an OpenID server in the same database.
The result of this function should be passed to the Consumer
constructor as the store parameter.
"""
db_engine = settings.DATABASES['default']['ENGINE']
if not db_engine:
return FileOpenIDStore(filestore_path)
# Possible side-effect: create a database connection if one isn't
# already open.
connection.cursor()
# Create table names to specify for SQL-backed stores.
tablenames = {
'associations_table': table_prefix + 'openid_associations',
'nonces_table': table_prefix + 'openid_nonces',
}
types = {
'django.db.backends.postgresql_psycopg2': sqlstore.PostgreSQLStore,
'django.db.backends.mysql': sqlstore.MySQLStore,
'django.db.backends.sqlite3': sqlstore.SQLiteStore,
}
if db_engine not in types:
raise ImproperlyConfigured(
"Database engine %s not supported by OpenID library" % db_engine)
s = types[db_engine](connection.connection, **tablenames)
try:
s.createTables()
except (SystemExit, KeyboardInterrupt, MemoryError):
raise
except:
# XXX This is not the Right Way to do this, but because the
# underlying database implementation might differ in behavior
# at this point, we can't reliably catch the right
# exception(s) here. Ideally, the SQL store in the OpenID
# library would catch exceptions that it expects and fail
# silently, but that could be bad, too. More ideally, the SQL
# store would not attempt to create tables it knows already
# exists.
pass
return s
def getViewURL(req, view_name_or_obj, args=None, kwargs=None):
relative_url = reverseURL(view_name_or_obj, args=args, kwargs=kwargs)
full_path = req.META.get('SCRIPT_NAME', '') + relative_url
return urljoin(getBaseURL(req), full_path)
def getBaseURL(req):
"""
Given a Django web request object, returns the OpenID 'trust root'
for that request; namely, the absolute URL to the site root which
is serving the Django request. The trust root will include the
proper scheme and authority. It will lack a port if the port is
standard (80, 443).
"""
name = req.META['HTTP_HOST']
try:
name = name[:name.index(':')]
except:
pass
try:
port = int(req.META['SERVER_PORT'])
except:
port = 80
proto = req.META['SERVER_PROTOCOL']
if 'HTTPS' in proto:
proto = 'https'
else:
proto = 'http'
if port in [80, 443] or not port:
port = ''
else:
port = ':%s' % (port,)
url = "%s://%s%s/" % (proto, name, port)
return url
def normalDict(request_data):
"""
Converts a django request MutliValueDict (e.g., request.GET,
request.POST) into a standard python dict whose values are the
first value from each of the MultiValueDict's value lists. This
avoids the OpenID library's refusal to deal with dicts whose
values are lists, because in OpenID, each key in the query arg set
can have at most one value.
"""
return dict((k, v) for k, v in request_data.items())
def renderXRDS(request, type_uris, endpoint_urls):
"""Render an XRDS page with the specified type URIs and endpoint
URLs in one service block, and return a response with the
appropriate content-type.
"""
response = render_to_response('xrds.xml',
{'type_uris': type_uris,
'endpoint_urls': endpoint_urls},
context_instance=RequestContext(request))
response['Content-Type'] = YADIS_CONTENT_TYPE
return response
|