Flask-OpenID-1.2.5/0000775000175000017500000000000012575547273016332 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/setup.cfg0000664000175000017500000000026312575547273020154 0ustar puiterwijkpuiterwijk00000000000000[build_sphinx] source-dir = docs/ build-dir = docs/_build all_files = 1 [upload_sphinx] upload-dir = docs/_build/html [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 Flask-OpenID-1.2.5/Flask_OpenID.egg-info/0000775000175000017500000000000012575547273022262 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/Flask_OpenID.egg-info/dependency_links.txt0000664000175000017500000000000112575547273026330 0ustar puiterwijkpuiterwijk00000000000000 Flask-OpenID-1.2.5/Flask_OpenID.egg-info/requires.txt0000664000175000017500000000003612575547273024661 0ustar puiterwijkpuiterwijk00000000000000Flask>=0.3 python-openid>=2.0 Flask-OpenID-1.2.5/Flask_OpenID.egg-info/not-zip-safe0000664000175000017500000000000112464145173024476 0ustar puiterwijkpuiterwijk00000000000000 Flask-OpenID-1.2.5/Flask_OpenID.egg-info/top_level.txt0000664000175000017500000000001512575547273025010 0ustar puiterwijkpuiterwijk00000000000000flask_openid Flask-OpenID-1.2.5/Flask_OpenID.egg-info/PKG-INFO0000664000175000017500000000206412575547273023361 0ustar puiterwijkpuiterwijk00000000000000Metadata-Version: 1.1 Name: Flask-OpenID Version: 1.2.5 Summary: OpenID support for Flask Home-page: http://github.com/mitsuhiko/flask-openid/ Author: Armin Ronacher, Patrick Uiterwijk Author-email: armin.ronacher@active-4.com, puiterwijk@redhat.com License: BSD Description: Flask-OpenID ============ Adds OpenID support to Flask. Links: * `Flask-OpenID Documentation `_ * `Flask `_ * `development version `_ Platform: any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-OpenID-1.2.5/Flask_OpenID.egg-info/SOURCES.txt0000664000175000017500000000202512575547273024145 0ustar puiterwijkpuiterwijk00000000000000LICENSE MANIFEST.in README flask_openid.py setup.cfg setup.py Flask_OpenID.egg-info/PKG-INFO Flask_OpenID.egg-info/SOURCES.txt Flask_OpenID.egg-info/dependency_links.txt Flask_OpenID.egg-info/not-zip-safe Flask_OpenID.egg-info/requires.txt Flask_OpenID.egg-info/top_level.txt docs/Makefile docs/conf.py docs/index.rst docs/make.bat docs/_static/flask-openid.png docs/_themes/.git docs/_themes/.gitignore docs/_themes/LICENSE docs/_themes/README docs/_themes/flask_theme_support.py docs/_themes/flask/layout.html docs/_themes/flask/relations.html docs/_themes/flask/theme.conf docs/_themes/flask/static/flasky.css_t docs/_themes/flask/static/small_flask.css docs/_themes/flask_small/layout.html docs/_themes/flask_small/theme.conf docs/_themes/flask_small/static/flasky.css_t example/README example/example.py example/flask-openid.db example/static/openid.png example/static/style.css example/templates/create_profile.html example/templates/edit_profile.html example/templates/index.html example/templates/layout.html example/templates/login.htmlFlask-OpenID-1.2.5/README0000664000175000017500000000026012464145144017174 0ustar puiterwijkpuiterwijk00000000000000Flask-OpenID ============ Adds support for OpenID to flask applications. Check out the example for more information. Documentation: http://packages.python.org/Flask-OpenID/ Flask-OpenID-1.2.5/LICENSE0000664000175000017500000000327312464145144017330 0ustar puiterwijkpuiterwijk00000000000000Copyright (c) 2010 by Armin Ronacher. Some rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------- OpenID® is a trademark (registered in numerous countries) of the OpenID Foundation. The OpenID logo in docs/_static/flask-openid.png is used under the OpenID trademark and service mark license, as defined on http://openid.net/trademark-license/. Flask-OpenID-1.2.5/MANIFEST.in0000664000175000017500000000036012464145144020053 0ustar puiterwijkpuiterwijk00000000000000include README LICENSE recursive-include docs * recursive-exclude docs *.pyc recursive-exclude docs *.pyo recursive-include example * recursive-exclude example *.pyc recursive-exclude example *.pyo prune docs/_build prune docs/_themes/.git Flask-OpenID-1.2.5/setup.py0000664000175000017500000000373112575547072020045 0ustar puiterwijkpuiterwijk00000000000000""" Flask-OpenID ============ Adds OpenID support to Flask. Links: * `Flask-OpenID Documentation `_ * `Flask `_ * `development version `_ """ from setuptools import setup import sys import os # This check is to make sure we checkout docs/_themes before running sdist if not os.path.exists("./docs/_themes/README"): print('Please make sure you have docs/_themes checked out while running setup.py!') if os.path.exists('.git'): print('You seem to be using a git checkout, please execute the following commands to get the docs/_themes directory:') print(' - git submodule init') print(' - git submodule update') else: print('You seem to be using a release. Please use the release tarball from PyPI instead of the archive from GitHub') sys.exit(1) extra = {} if sys.version_info[0] >= 3: install_requires = ['Flask>=0.10.1', 'python3-openid>=2.0'] extra['use_2to3'] = True else: install_requires = ['Flask>=0.3', 'python-openid>=2.0'] setup( name='Flask-OpenID', version='1.2.5', url='http://github.com/mitsuhiko/flask-openid/', license='BSD', author='Armin Ronacher, Patrick Uiterwijk', author_email='armin.ronacher@active-4.com, puiterwijk@redhat.com', description='OpenID support for Flask', long_description=__doc__, py_modules=['flask_openid'], zip_safe=False, platforms='any', install_requires=install_requires, classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' ], **extra ) Flask-OpenID-1.2.5/example/0000775000175000017500000000000012575547273017765 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/example/README0000664000175000017500000000021412464145144020626 0ustar puiterwijkpuiterwijk00000000000000This folder contains a very basic example for OpenID integration. You can just run "python example.py" (after you installed flask-openid). Flask-OpenID-1.2.5/example/flask-openid.db0000644000175000017500000000400012575544352022633 0ustar puiterwijkpuiterwijk00000000000000SQLite format 3@ - ff tableusersusersCREATE TABLE users ( id INTEGER NOT NULL, name VARCHAR(60), email VARCHAR(200), openid VARCHAR(200), PRIMARY KEY (id) ) Flask-OpenID-1.2.5/example/example.py0000775000175000017500000001311212575545733021772 0ustar puiterwijkpuiterwijk00000000000000#!/bin/env python # -*- coding: utf-8 -*- """ OpenID Example ~~~~~~~~~~~~~~ This simple application shows how to integrate OpenID in your application. This example requires SQLAlchemy as a dependency. :copyright: (c) 2010 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ from flask import Flask, render_template, request, g, session, flash, \ redirect, url_for, abort from flask.ext.openid import OpenID from openid.extensions import pape from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.ext.declarative import declarative_base # setup flask app = Flask(__name__) app.config.update( DATABASE_URI = 'sqlite:///flask-openid.db', SECRET_KEY = 'development key', DEBUG = True ) # setup flask-openid oid = OpenID(app, safe_roots=[], extension_responses=[pape.Response]) # setup sqlalchemy engine = create_engine(app.config['DATABASE_URI']) db_session = scoped_session(sessionmaker(autocommit=True, autoflush=True, bind=engine)) Base = declarative_base() Base.query = db_session.query_property() def init_db(): Base.metadata.create_all(bind=engine) class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(60)) email = Column(String(200)) openid = Column(String(200)) def __init__(self, name, email, openid): self.name = name self.email = email self.openid = openid @app.before_request def before_request(): g.user = None if 'openid' in session: g.user = User.query.filter_by(openid=session['openid']).first() @app.after_request def after_request(response): db_session.remove() return response @app.route('/') def index(): return render_template('index.html') @app.route('/login', methods=['GET', 'POST']) @oid.loginhandler def login(): """Does the login via OpenID. Has to call into `oid.try_login` to start the OpenID machinery. """ # if we are already logged in, go back to were we came from if g.user is not None: return redirect(oid.get_next_url()) if request.method == 'POST': openid = request.form.get('openid') if openid: pape_req = pape.Request([]) return oid.try_login(openid, ask_for=['email', 'nickname'], ask_for_optional=['fullname'], extensions=[pape_req]) return render_template('login.html', next=oid.get_next_url(), error=oid.fetch_error()) @oid.after_login def create_or_login(resp): """This is called when login with OpenID succeeded and it's not necessary to figure out if this is the users's first login or not. This function has to redirect otherwise the user will be presented with a terrible URL which we certainly don't want. """ session['openid'] = resp.identity_url if 'pape' in resp.extensions: pape_resp = resp.extensions['pape'] session['auth_time'] = pape_resp.auth_time user = User.query.filter_by(openid=resp.identity_url).first() if user is not None: flash(u'Successfully signed in') g.user = user return redirect(oid.get_next_url()) return redirect(url_for('create_profile', next=oid.get_next_url(), name=resp.fullname or resp.nickname, email=resp.email)) @app.route('/create-profile', methods=['GET', 'POST']) def create_profile(): """If this is the user's first login, the create_or_login function will redirect here so that the user can set up his profile. """ if g.user is not None or 'openid' not in session: return redirect(url_for('index')) if request.method == 'POST': name = request.form['name'] email = request.form['email'] if not name: flash(u'Error: you have to provide a name') elif '@' not in email: flash(u'Error: you have to enter a valid email address') else: flash(u'Profile successfully created') db_session.add(User(name, email, session['openid'])) db_session.commit() return redirect(oid.get_next_url()) return render_template('create_profile.html', next_url=oid.get_next_url()) @app.route('/profile', methods=['GET', 'POST']) def edit_profile(): """Updates a profile""" if g.user is None: abort(401) form = dict(name=g.user.name, email=g.user.email) if request.method == 'POST': if 'delete' in request.form: db_session.delete(g.user) db_session.commit() session['openid'] = None flash(u'Profile deleted') return redirect(url_for('index')) form['name'] = request.form['name'] form['email'] = request.form['email'] if not form['name']: flash(u'Error: you have to provide a name') elif '@' not in form['email']: flash(u'Error: you have to enter a valid email address') else: flash(u'Profile successfully created') g.user.name = form['name'] g.user.email = form['email'] db_session.commit() return redirect(url_for('edit_profile')) return render_template('edit_profile.html', form=form) @app.route('/logout') def logout(): session.pop('openid', None) flash(u'You have been signed out') return redirect(oid.get_next_url()) if __name__ == '__main__': init_db() app.run() Flask-OpenID-1.2.5/example/templates/0000775000175000017500000000000012575547273021763 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/example/templates/login.html0000664000175000017500000000062612464145144023751 0ustar puiterwijkpuiterwijk00000000000000{% extends "layout.html" %} {% block title %}Sign in{% endblock %} {% block body %}

Sign in

{% if error %}

Error: {{ error }}

{% endif %}

OpenID:

{% endblock %} Flask-OpenID-1.2.5/example/templates/layout.html0000664000175000017500000000120212464145144024145 0ustar puiterwijkpuiterwijk00000000000000 {% block title %}Welcome{% endblock %} | Flask OpenID Example

Flask OpenID Example

{% for message in get_flashed_messages() %}

{{ message }} {% endfor %} {% block body %}{% endblock %} Flask-OpenID-1.2.5/example/templates/edit_profile.html0000664000175000017500000000073112464145144025303 0ustar puiterwijkpuiterwijk00000000000000{% extends "layout.html" %} {% block title %}Edit Profile{% endblock %} {% block body %}

Edit Profile

Name:
E-Mail

{% endblock %} Flask-OpenID-1.2.5/example/templates/index.html0000664000175000017500000000032512464145144023744 0ustar puiterwijkpuiterwijk00000000000000{% extends "layout.html" %} {% block body %}

Overview

{% if g.user %}

Hello {{ g.user.name }}! {% endif %}

This is just an example page so that something is here. {% endblock %} Flask-OpenID-1.2.5/example/templates/create_profile.html0000664000175000017500000000134612464145144025624 0ustar puiterwijkpuiterwijk00000000000000{% extends "layout.html" %} {% block title %}Create Profile{% endblock %} {% block body %}

Create Profile

Hey! This is the first time you signed in on this website. In order to proceed we need some extra information from you:

Name:
E-Mail:

If you don't want to proceed, you can sign out again. {% endblock %} Flask-OpenID-1.2.5/example/static/0000775000175000017500000000000012575547273021254 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/example/static/style.css0000664000175000017500000000121012464145144023104 0ustar puiterwijkpuiterwijk00000000000000body { font-family: 'Georgia', serif; font-size: 16px; margin: 30px; padding: 0; } a { color: #335E79; } p.message { color: #335E79; padding: 10px; background: #CADEEB; } p.error { color: #783232; padding: 10px; background: #EBCACA; } input { font-family: 'Georgia', serif; font-size: 16px; border: 1px solid black; color: #335E79; padding: 2px; } input[type="submit"] { background: #CADEEB; color: #335E79; border-color: #335E79; } input[name="openid"] { background: url(openid.png) 4px no-repeat; padding-left: 24px; } h1, h2 { font-weight: normal; } Flask-OpenID-1.2.5/flask_openid.py0000664000175000017500000005413312575546334021345 0ustar puiterwijkpuiterwijk00000000000000# -* coding: utf-8 -*- """ flaskext.openid ~~~~~~~~~~~~~~~ Tiny wrapper around python-openid to make working with the basic API in a flask application easier. Adapt this code for your own project if necessary. :copyright: (c) 2010 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import os import pickle import tempfile from functools import wraps from datetime import date import sys import base64 from flask import request, session, redirect, current_app, url_for from werkzeug.urls import url_quote from openid.store.filestore import FileOpenIDStore from openid.extensions import ax from openid.extensions.sreg import SRegRequest, SRegResponse from openid.consumer.consumer import Consumer, SUCCESS, CANCEL, FAILURE, \ SETUP_NEEDED from openid.consumer import discover # python-openid is a really stupid library in that regard, we have # to disable logging by monkey patching. We still call the original # implementation if we are in debug mode though. from openid import oidutil _original_log = oidutil.log def _dispatching_log(message, level=None): app = current_app._get_current_object() if app is None or app.debug: return _original_log(message, level) oidutil.log = _dispatching_log AX_MAPPING = { 'nickname': ['http://axschema.org/namePerson/friendly', 'http://schema.openid.net/namePerson/friendly'], 'email': ['http://axschema.org/contact/email', 'http://schema.openid.net/contact/email'], 'fullname': ['http://axschema.org/namePerson', 'http://axschema.org/namePerson/first', 'http://axschema.org/namePerson/last', 'http://schema.openid.net/namePerson'], 'dob': ['http://axschema.org/birthDate', 'http://axschema.org/birthDate/birthYear', 'http://axschema.org/birthDate/birthMonth', 'http://schema.openid.net/birthDate'], 'gender': ['http://axschema.org/person/gender', 'http://schema.openid.net/person/gender'], 'postcode': ['http://axschema.org/contact/postalCode/home', 'http://schema.openid.net/contact/postalCode/home'], 'country': ['http://axschema.org/contact/country/home', 'http://schema.openid.net/contact/country/home'], 'language': ['http://axschema.org/pref/language', 'http://schema.openid.net/pref/language'], 'timezone': ['http://axschema.org/pref/timezone', 'http://schema.openid.net/pref/timezone'], 'phone': ['http://axschema.org/contact/phone/default'], 'aim': ['http://axschema.org/contact/IM/AIM'], 'icq': ['http://axschema.org/contact/IM/ICQ'], 'msn': ['http://axschema.org/contact/IM/MSN'], 'yahoo': ['http://axschema.org/contact/IM/Yahoo'], 'jabber': ['http://axschema.org/contact/IM/Jabber'], 'skype': ['http://axschema.org/contact/IM/Skype'], 'website': ['http://axschema.org/contact/web/default', 'http://schema.openid.net/contact/web/default'], 'blog': ['http://axschema.org/contact/web/blog'], 'image': ['http://axschema.org/media/image/default', 'http://schema.openid.net/media/image/default'] } FULL_NAME_URIS = ['http://axschema.org/namePerson', 'http://schema.openid.net/namePerson'] FULL_DOB_URIS = ['http://axschema.org/birthDate', 'http://schema.openid.net/birthDate'] SREG_KEYS = set(['nickname', 'email', 'fullname', 'dob', 'gender', 'postcode', 'country', 'language', 'timezone']) # these are required if provided, otherwise google will not return # the information for the application. REQUIRED_KEYS = set(['country', 'email', 'fullname', 'language']) ALL_KEYS = set(AX_MAPPING) | SREG_KEYS COMMON_PROVIDERS = { 'google': 'https://www.google.com/accounts/o8/id', 'yahoo': 'https://yahoo.com/', 'aol': 'http://aol.com/', 'steam': 'https://steamcommunity.com/openid/' } def softint(x): try: return int(x) except (ValueError, TypeError): return None def isstring(x): if sys.version_info[0] >= 3: return isinstance(x, str) else: return isinstance(x, basestring) class SessionWrapper(object): name_mapping = { '_yadis_services__openid_consumer_': 'yoc', '_openid_consumer_last_token': 'lt' } def __init__(self, ext): self.ext = ext def __getitem__(self, name): rv = session[self.name_mapping.get(name, name)] if isinstance(rv, dict) and len(rv) == 1 and ' p' in rv: try: return pickle.loads(base64.b64decode(rv[' p'].encode('utf-8'))) except: return pickle.loads(rv[' p']) return rv def __setitem__(self, name, value): if not getattr(current_app.session_interface, 'pickle_based', True): b64 = base64.b64encode(pickle.dumps(value, 0)) value = {' p': b64.decode('utf-8')} session[self.name_mapping.get(name, name)] = value def __delitem__(self, name): del session[self.name_mapping.get(name, name)] def get(self, name, default=None): try: return self[name] except KeyError: return default def __contains__(self, name): try: self[name] return True except KeyError: return False class RegLookup(object): def __init__(self, resp, extensions): sreg_resp = SRegResponse.fromSuccessResponse(resp) self.sreg = sreg_resp and sreg_resp.data or {} self.ax_resp = ax.FetchResponse.fromSuccessResponse(resp) or {} # Process the OpenID response with the OpenIDResponse class provided self.ext = {} for extension in extensions: ext_name = getattr(extension, 'ns_alias', extension.__name__) self.ext[ext_name] = \ extension.fromSuccessResponse(resp) def get(self, name, default=None): assert name in ALL_KEYS, 'unknown key %r' % name rv = self.sreg.get(name) if rv is not None: return rv for uri in AX_MAPPING.get(name, ()): rv = self.get_uri(uri) if rv is not None: return rv return default def get_uri(self, uri): try: return self.ax_resp.get(uri)[0] except (TypeError, IndexError, KeyError): return None def get_combined(self, sreg_key, ax_uris): rv = self.sreg.get(sreg_key) if rv is not None: return rv for uri in ax_uris: rv = self.get_uri(uri) if rv is not None: return rv class OpenIDResponse(object): """Passed to the `after_login` function. Provides all the information sent from the OpenID provider. The profile information has to be requested from the server by passing a list of fields as `ask_for` to the :meth:`~OpenID.try_login` function. """ def __init__(self, resp, extensions): #: the openid the user used for sign in self.identity_url = resp.identity_url lookup = RegLookup(resp, extensions) #: the full name of the user self.fullname = lookup.get_combined('fullname', FULL_NAME_URIS) if self.fullname is None: first = lookup.get_uri('http://axschema.org/namePerson/first') last = lookup.get_uri(u'http://axschema.org/namePerson/last') self.fullname = u' '.join(x for x in [first, last] if x) or None #: desired nickname of the user self.nickname = lookup.get('nickname') #: the email address of the user self.email = lookup.get('email') #: the gender of the user (``f`` for femail and ``m`` for male) self.gender = (lookup.get('gender') or '').lower() or None #: the country of the user as specified by ISO3166 self.country = lookup.get('country') #: free text that should conform to the user's country's postal system self.postcode = lookup.get('postcode') #: the user's preferred language as specified by ISO639 self.language = lookup.get('language') #: timezone string from the TimeZone database self.timezone = lookup.get('timezone') #: date of birth as :class:`~datetime.datetime` object. self.date_of_birth = None #: the year of birth of the user as integer self.year_of_birth = None #: the month of birth of the user as integer (1 based) self.month_of_birth = None # check if we can get the full birthday first dobstr = lookup.get_combined('dob', FULL_DOB_URIS) if dobstr is not None: try: pieces = [int(x) for x in dobstr.split('-')] if len(pieces) != 3: raise ValueError() except (ValueError, TypeError): pass else: if pieces[0]: self.year_of_birth = pieces[0] if pieces[1]: self.month_of_birth = pieces[1] try: self.date_of_birth = date(*pieces) except (ValueError, TypeError, OverflowError): pass # next try just year and month if self.year_of_birth is None: self.year_of_birth = softint(lookup.get_uri( 'http://axschema.org/birthDate/birthYear')) self.month_of_birth = softint(lookup.get_uri( 'http://axschema.org/birthDate/birthMonth')) #: phone number of the user as string self.phone = lookup.get('phone') #: AIM messenger address as string self.aim = lookup.get('aim') #: icq messenger number as string self.icq = lookup.get('icq') #: msn name as string self.msn = lookup.get('msn') #: yahoo messenger address as string self.yahoo = lookup.get('yahoo') #: jabber address as string self.jabber = lookup.get('jabber') #: skype name as string self.skype = lookup.get('skype') #: URL of website as string self.website = lookup.get('website') #: URL of blog as string self.blog = lookup.get('blog') #: URL to profile image as string self.image = lookup.get('image') #: Hash of the response object from the OpenID Extension by the # OpenID Extension class name self.extensions = lookup.ext class OpenID(object): """Simple helper class for OpenID auth. Has to be created in advance like a :class:`~flask.Flask` object. There are two usage modes which work very similar. One is binding the instance to a very specific Flask application:: app = Flask(__name__) db = OpenID(app) The second possibility is to create the object once and configure the application later to support it:: oid = OpenID() def create_app(): app = Flask(__name__) oid.init_app(app) return app :param app: the application to register this openid controller with. :param fs_store_path: if given this is the name of a folder where the OpenID auth process can store temporary information. If neither is provided a temporary folder is assumed. This is overridden by the ``OPENID_FS_STORE_PATH`` configuration key. :param store_factory: alternatively a function that creates a python-openid store object. :param fallback_endpoint: optionally a string with the name of an URL endpoint the user should be redirected to if the HTTP referrer is unreliable. By default the user is redirected back to the application's index in that case. :param extension_responses: a list of OpenID Extensions Response class. :param safe_roots: a list of trust roots to support returning to :param url_root_as_trust_root: whether to use the url_root as trust_root """ def __init__(self, app=None, fs_store_path=None, store_factory=None, fallback_endpoint=None, extension_responses=None, safe_roots=None, url_root_as_trust_root=False): # backwards compatibility support if isstring(app): from warnings import warn warn(DeprecationWarning('OpenID constructor expects application ' 'as first argument now. If you want to ' 'provide a hardcoded fs_store_path you ' 'have to use a keyword argument. It is ' 'recommended though to use the config ' 'key.'), stacklevel=2) fs_store_path = app app = None self.app = app if app is not None: self.init_app(app) self.fs_store_path = fs_store_path if store_factory is None: store_factory = self._default_store_factory self.store_factory = store_factory self.after_login_func = None self.fallback_endpoint = fallback_endpoint if not extension_responses: extension_responses = [] self.extension_responses = extension_responses if isstring(safe_roots): self.safe_roots = [safe_roots] else: self.safe_roots = safe_roots self.url_root_as_trust_root = url_root_as_trust_root def init_app(self, app): """This callback can be used to initialize an application for the use with this openid controller. .. versionadded:: 1.0 """ app.config.setdefault('OPENID_FS_STORE_PATH', None) def _default_store_factory(self): """Default store factory that creates a filesystem store from the configuration. """ app = self.app if self.app is not None else current_app if 'OPENID_FS_STORE_PATH' not in app.config: self.init_app(app) from warnings import warn warn(DeprecationWarning('init_app not called for this ' 'application. This is deprecated functionality')) path = app.config['OPENID_FS_STORE_PATH'] or self.fs_store_path if path is None: path = os.path.join(tempfile.gettempdir(), 'flask-openid') return FileOpenIDStore(path) def signal_error(self, msg): """Signals an error. It does this by storing the message in the session. Use :meth:`errorhandler` to this method. """ session['openid_error'] = msg def fetch_error(self): """Fetches the error from the session. This removes it from the session and returns that error. This method is probably useless if :meth:`errorhandler` is used. """ return session.pop('openid_error', None) def get_next_url(self): """Returns the URL where we want to redirect to. This will always return a valid URL. """ return ( self.check_safe_root(request.values.get('next')) or self.check_safe_root(request.referrer) or (self.fallback_endpoint and self.check_safe_root(url_for(self.fallback_endpoint))) or request.url_root ) def check_safe_root(self, url): if url is None: return None if self.safe_roots is None: return url if url.startswith(request.url_root) or url.startswith('/'): # A URL inside the same app is deemed to always be safe return url for safe_root in self.safe_roots: if url.startswith(safe_root): return url return None def get_current_url(self): """the current URL + next.""" return request.base_url + '?next=' + url_quote(self.get_next_url()) def get_success_url(self): """Return the internal success URL. :internal: """ return self.get_current_url() + '&openid_complete=yes' def attach_reg_info(self, auth_request, keys, optional_keys): """Attaches sreg and ax requests to the auth request. :internal: """ keys = set(keys or []) optional_keys = set(optional_keys or []) sreg_keys = list(SREG_KEYS & keys) sreg_optional_keys = list(SREG_KEYS & optional_keys) auth_request.addExtension(SRegRequest(required=sreg_keys, optional=sreg_optional_keys)) ax_req = ax.FetchRequest() for key in (keys | optional_keys): for uri in AX_MAPPING.get(key, ()): ax_req.add(ax.AttrInfo(uri, required=key in REQUIRED_KEYS)) auth_request.addExtension(ax_req) def errorhandler(self, f): """Called if an error occurs with the message. By default ``'openid_error'`` is added to the session so that :meth:`fetch_error` can fetch that error from the session. Alternatively it makes sense to directly flash the error for example:: @oid.errorhandler def on_error(message): flash(u'Error: ' + message) """ self.signal_error = f return f def after_login(self, f): """This function will be called after login. It must redirect to a different place and remember the user somewhere. The session is not modified by SimpleOpenID. The decorated function is passed a :class:`OpenIDResponse` object. """ self.after_login_func = f return f def loginhandler(self, f): """Marks a function as login handler. This decorator injects some more OpenID required logic. Always decorate your login function with this decorator. """ @wraps(f) def decorated(*args, **kwargs): if request.args.get('openid_complete') != u'yes': return f(*args, **kwargs) consumer = Consumer(SessionWrapper(self), self.store_factory()) args = request.args.to_dict() args.update(request.form.to_dict()) openid_response = consumer.complete(args, self.get_current_url()) if openid_response.status == SUCCESS: return self.after_login_func(OpenIDResponse( openid_response, self.extension_responses)) elif openid_response.status == CANCEL: self.signal_error(u'The request was cancelled') elif openid_response.status == FAILURE: self.signal_error(u'OpenID authentication failure. Mesage: %s' % openid_response.message) elif openid_response.status == SETUP_NEEDED: # Unless immediate=True, we should never get here self.signal_error(u'OpenID setup was needed') else: # We should also never get here, as this should be exhaustive self.signal_error(u'OpenID authentication weird state: %s' % openid_response.status) return redirect(self.get_current_url()) return decorated def try_login(self, identity_url, ask_for=None, ask_for_optional=None, extensions=None, immediate=False): """This tries to login with the given identity URL. This function must be called from the login_handler. The `ask_for` and `ask_for_optional`parameter can be a set of values to be asked from the openid provider, where keys in `ask_for` are marked as required, and keys in `ask_for_optional` are marked as optional. The following strings can be used in the `ask_for` and `ask_for_optional` parameters: ``aim``, ``blog``, ``country``, ``dob`` (date of birth), ``email``, ``fullname``, ``gender``, ``icq``, ``image``, ``jabber``, ``language``, ``msn``, ``nickname``, ``phone``, ``postcode``, ``skype``, ``timezone``, ``website``, ``yahoo`` `extensions` can be a list of instances of OpenID extension requests that should be passed on with the request. If you use this, please make sure to pass the Response classes of these extensions when initializing OpenID. `immediate` can be used to indicate this request should be a so-called checkid_immediate request, resulting in the provider not showing any UI. Note that this adds a new possible response: SetupNeeded, which is the server saying it doesn't have enough information yet to authorized or reject the authentication (probably, the user needs to sign in or approve the trust root). """ if ask_for and __debug__: for key in ask_for: if key not in ALL_KEYS: raise ValueError('invalid key %r' % key) if ask_for_optional: for key in ask_for_optional: if key not in ALL_KEYS: raise ValueError('invalid optional key %r' % key) try: consumer = Consumer(SessionWrapper(self), self.store_factory()) auth_request = consumer.begin(identity_url) if ask_for or ask_for_optional: self.attach_reg_info(auth_request, ask_for, ask_for_optional) if extensions: for extension in extensions: auth_request.addExtension(extension) except discover.DiscoveryFailure: self.signal_error(u'The OpenID was invalid') return redirect(self.get_current_url()) if self.url_root_as_trust_root: trust_root = request.url_root else: trust_root = request.host_url return redirect(auth_request.redirectURL(trust_root, self.get_success_url(), immediate=immediate)) Flask-OpenID-1.2.5/docs/0000775000175000017500000000000012575547273017262 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/docs/Makefile0000664000175000017500000001073112464145144020710 0ustar puiterwijkpuiterwijk00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Classy.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Classy.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Classy" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Classy" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." latexpdf: latex $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." Flask-OpenID-1.2.5/docs/_static/0000775000175000017500000000000012575547273020710 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/docs/_static/flask-openid.png0000664000175000017500000003300412464145144023756 0ustar puiterwijkpuiterwijk00000000000000PNG  IHDRb5 +vsBIT|d pHYsa(atEXtSoftwarewww.inkscape.org< IDATxy]?߈ "!1ER,yfZ5LR3EҚfZCs1&]'ws>>ýYϽwk>kef̨HZ8̶ku_"H$i'z@d`}`f6݊D"Hm4IcՀZکH$DڌF i!@` 3{'7``+D"H5zK:x̦  zsD"HzA+UlBiF"H$D$N0\H$DQZT` fjx"H$F Y3U*.qR$D"#&FIZQU !D""AҏB$D" z88 j"H$)'Ly8F'H$D5H$& < dfTp}."~%Ei.A3>fn, \]}*ښjfҫI3&JQ!&2 }6s`a|8XF#pWB8sf>0k9J0` J۾J۟% UH3k`z̦k鼒n5%-`fv~JT+qC܌T Q8 3"lX_5KM#h  CB6vd3osWk> ` =Pa{^ӘYS񝁿q!a@. /@ݺ5^?3p(nb6ٖ(Y/ٸ Yڲ*x۴9|pEsl{! kz`V޸5n5̑ط:pO3؇ŷ11|A>S5m)40$-;:.lfrjJlQ:t"ݞS~ | \ \bfP$\y 0jRx[ *8:9L2hZvZI%N(Vz_oNۘ]MRHx q^oY Ď7g,J Ǚ \$7ً ݐ:7ј0K5p pk$~ǚ of#5 f6^ָ9 -3۫{4/nQIf61>פ-F#f6F&d%t;p'] ֔sD\0}(lHof m]Iҟۆ}H+Pߑ @HnM90:khf?)pipDR_ 6COvlکK'6:ap pqҹfh5!)xD@bf_J:w?`GI*:\ o]< -FIz WKXQ݅٘ &up=#lpP77+C3pY˸o`Iת%YZr[Ȍl$}G;w{^I˓vK]8p0[$Gpo:UyH_C kxli9E?VC;3CQ33yޗ-Zݿ*>G/`?#~Z}{f+يkV?-i>w$⃀S}#qU\p;^5;Zڭ;rHzFx_cfg[<CSFYs3 Y]1--l uk *>(TAL4 QXw \g~AHvmhfWX lyXq%8)--3P/f=dff expJZh%x, 9{⎇s3Z۬%-0I7zr 8VҫtuB~`fߘ;,k ] &돸ګ@B`l( 4n/ H:74q㋛fV^4qf }e\{p!faVaVIg(Q£N inU5/p(m`Ő p)9Oh))4-ӛ}+0di1.c9:ُƝ#)ڼ#F.40%;-[[RB0aQ>BB3O҅-~`U !up\^.)AHg\8xxTDgD3{< Ú6~,!~fxOBO!irJ=/i-|>̶K8KҦcHǓofٯьI9>tIlf_f^E6<`KjٴE35rn: hp&v\qGKʣ:mu`fo _'O~,@B߽U'T3U+nnPV`]N2]gf[&+$mr?4xڌfixr%oGaɍAX lco՗HChk6Ȟ!><^WAq#f(V1A+n6'BofGɳ0$ܖP4mm;AEZ&x&2`7+ʁ 0N gJI`S)aO6>G!TC\9sQf*Mĵcjdzm# vJ:/ IVַ:${Oz)+ ^衜WW+tl+i_k\uߕ( v~1r8J% k4+)5<$_zyv.DO;S "h1ቚLn$m 6x x4Ǹ0'0H$|{=Yýf&$…'zu,ПOZ:Kx Sn.XI˚Y`YIs'%M N_̍$ t.of @>+WGi+IMh jF-TN(8_T$%g 9iN7³@.kfsRfm~΋O{ f۸u qkffnf5ypb4p%\66j<7O9$탇^s]3̖ ns~+C &ir]vv OV7A?^tgKpفr׬A(^ ˩S (m9AEZNŽHx ϴhfZfsh[)g g O}yhwy3;23ef Q⠩H[܌ I Cp9 X̾NY0(Psb"KŮk ԝ4R*mhB&"If6I}}C7MJڑ/p^ӥbt٧qShfqI[ٻ|&yvq,#G3㦆%!k x(]OH7 8ql  0sӄ6&78X}uiѸvA88>8$fFmٷfv'3zuap= QЦt-z40t B ,Ut`% ;_|p?$sEg0mk!86%QMuu|'議 7hid_3z.bY³&qǬs_SgWq;}QSf7|j+Ҹmx홬Їfv~܃ +$'Jf=% +YGRj Óp,pKz IP_K H׻XfmfUїo$>/a,xy `a՜IrA0k_<PR;55wo 4L@ nM1.8&nˈS/++^̍{-p 𱤍6ռy@ZDcS,4|C?*П`˼P\K2 |U\ЄލVĕ`f56 >_G$]b #v4/+\K"`otJFI^} ׊w򋨒%^pr4g#yQ@LAPi& 2` 'Ftdqwꨀ0Pj$mk.a+`}IT᫕N050nM'牸_MA*7I ,n½7(RcUV3,h.W<,<\Sd:<$|r_kP$3TS|sb!h ./E'qt֖3]:t`,ې-K3Y9S?jW#|؟tCZOW BI!i yi"8I'@+n.d#\`a__\Hȃ#$=j`+qEaI]Ԅql1 A/g#—@wA#1WEO9fQ]DI=YpS=|xs'xַ:6VZK+=VRRz CW+Qnfpo~x|)*=<Ͱ24Oe_+:<X>CoƝҘ޵ElgRWU)g+͛ _y| x8ogO3iib7x͆] kpna,pWZ" UԇPba;aߣD`gvEJ ]F ԫA(8eqed4x^,_uU4h5luI63Tk!4rX}No紧a ]s WvX 74ɉY:r7Y`!y/Б&8M0XK O!K3|^_2 WczW~!.kb( 3wRj㫙E,xqFص%݁{Qgb`iaW$g+<ɷXQE_^䜢ݯ[>ے|G7L66)¢tf8 DI܏daģhF<9D}Ї>82BrL^B_  ,g YG<˞L8D% u}N5pUޘj Yg QMfcI4n#S 'Y#IcdgHC:AkRx!yOP$ g]Tx܇#ׇiB%b>終~t3]ce"Bj%I=EmbAY_z4.s|It(n(^|$/f dMC9t BZ Bk! BD\C;A[\j̞4%BA@X!c=_jk9oppB\JvJ荨OKS oKHZ ۤ~c <It;}J׏h6{ևhbq'$LSqռÔIc'!&޳6)ciTuIDAT~$E1Mj,%i \H)B[oy&IzOsJ7Y ]m"[~Iv=*KS誢 9䞸z3C…V _Qb9_oe޸kNVOAhBqk˞/MB1{ҹjb1u46$m-ReCpѣ%\:5+xO&oqG,!?$Gp-Hzs[D!R; mӟࡆ)%<]@(`fߘ٥F7xr%|)5+.MY'i 3H 'KKګh:#h8jH`D y7\sV]xҶ;wYq^bBx\=|FJIV } oPJ4acE.G'5XE;;٧}I ND Bw H 53 X̊3ek3mۥ{Q>>,ѧs BB̐dI&?Xo@y2jhv`ȋ,Yk-eϋggHƙ7n]0~@GWCɓԦAhARoI⦿lBZk3pgj퀙] W^ŭYDz!`ԢfX'SfJƱ45  J՘H3&dQ-PA{tָ0В(IʳR!B!_ F__<'iZ; > ;&jgt+j)TVJ@UNZK΄3JZ6 OeڟEeރ\x`f׆N):vpkV]HZIu}W3C)gjh~vMI_%TBnfW'o;Nr;N:(y>*''{9\PԷ^bxb_k(i I?tzEܡs 3$qxhdh{:}P3"i?>Io%%j0o$mG5<%i[3{*$ Sj/%!YK[!X0ıjU3*i@5%ª}qjXıo~% 3;U(i ;)iu\ 3JP\C𽢁nvYW; M*f6>+K::*U+H7+kfOg]of$o)WC$is\]ɳ$f6JPy0J,uJdS;|ڜQK٧vk+~y26w-{VΆbgW+<Ӷ2qh`*>Ts x,\ H`S YEnF)''LG|~ ,ڷR«'wQ2.Zb.0g5y.rlp-4y?Ч9_1|20h xg8hmľՓyLij&O _;pz;8' Y%j{~Ky*{yZt}*lw\(0nXAך?̹B^Ci:_3tY,wb%'%3>|nۏky8܂ˆ+'K s. .'13=%͚ޏ=S&}GpAa:!zB! |Vo9 mtxB3~Wױ:X=y$Wquo۔*?ZMQ~Oj>[I}`{lFejr _xf£>>WVa.`NsQ{i!ϐ9׊T.6CJ痸fZ4jVf}H\`x 7)+~aзA@}Z,=ЖӼ?lľ삢sW7C+O\<_pz<s90~(ɉsߡC )1Sc(>B bpR}7Og!gsVߧYe2>O.}*%ڜWJ>sr.y+yoWu$0w˞~'Y*tM1 ުHQZtVrw"x6UX>ȹȳ}B>@Yɰ>yA/鍖R!x߃" |^Ϯ=>kL:K g X\ƶVJ ~{| l^ak`.s ^p2/}_V$UЏ4aoܼT\lp|Q96 }Oߌ #ǝ'xd:4#q@Ucz͊DJygRg=ݟ|%$G (Q3H@~KO2&`⫄qe-UB[\!l\ U8'!iN9ld;w)ʾ,61SB_+儃B𲸍|>\z7l3 &F-ɻa[GZ}I~Jf2>}=m_ V&!,@vWSgw4gxZF5d(y/M@8wJLڝ0.5)"mDU@ӼO{.nIj>0|]t~sG"H[!  |]Hjb. ,"i<;dfF3 w9_)]aJ"ȌDOiCj13h[Հjhf 75. n,lK~6& H{Hé n#I{bCڅt3-'y'.(#HBlfl_gO%)IHZg' i)IqP3>:!F"F" a&RHJU8TWx.vI~``HE{ ` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Classy.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Classy.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end Flask-OpenID-1.2.5/docs/conf.py0000664000175000017500000001570112464145144020551 0ustar puiterwijkpuiterwijk00000000000000# -*- coding: utf-8 -*- # # Flask-OpenID documentation build configuration file, created by # sphinx-quickstart on Mon Apr 26 19:53:01 2010. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.append(os.path.abspath('_themes')) sys.path.append(os.path.abspath('..')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Flask-OpenID' copyright = u'2010, Armin Ronacher' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '1.0' # The full version, including alpha/beta/rc tags. release = '1.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'flask_small' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = { 'index_logo': 'flask-openid.png', 'github_fork': 'mitsuhiko/flask-openid' } # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['_themes'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = 'Flask-OpenID' # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'Flask-OpenIDdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Flask-OpenID.tex', u'Flask-OpenID Documentation', u'Armin Ronacher', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'flask-openid', u'Flask-OpenID Documentation', [u'Armin Ronacher'], 1) ] intersphinx_mapping = { 'http://docs.python.org/dev': None, 'http://flask.pocoo.org/docs': None } Flask-OpenID-1.2.5/docs/index.rst0000664000175000017500000002340112575541705021115 0ustar puiterwijkpuiterwijk00000000000000Flask-OpenID ============ .. module:: flask_openid Flask-OpenID is an extension to `Flask`_ that allows you to add `OpenID`_ based authentication to your website in a matter of minutes. It depends on Flask and `python-openid`_ 2.x. You can install the requirements from PyPI with `easy_install` or `pip` or download them by hand. Features -------- - support for OpenID 2.x - friendly API - perfect integration into Flask - basic support for AX and SReg extensions to OpenID that make it possible to fetch basic profile information from a user's OpenID provider. Installation ------------ Install the extension with one of the following commands:: $ easy_install Flask-OpenID or alternatively if you have `pip` installed:: $ pip install Flask-OpenID How to Use ---------- To integrate Flask-OpenID into your application you need to create an instance of the :class:`OpenID` object first:: from flask.ext.openid import OpenID oid = OpenID(app, '/path/to/store', safe_roots=[]) By default it will use the filesystem as store for information needed by OpenID for the authentication process. You can alternatively implement your own store that uses the database or a no-sql server. For more information about that, consult the python-openid documentation. The path to the store can also be specified with the ``OPENID_FS_STORE_PATH`` configuration variable. Alternatively the object can be instantiated without the application in which case it can later be registered for an application with the :meth:`~OpenID.init_app` method. The list of URL roots that are safe to redirect the user to are passed via `safe_roots`. Whenever the url root of the ``'next'`` request argument is not in this list, the user will get redirected to the app root. All urls that are local to the current app are always regared as trusted. This security mechanism can be disabled by leaving `safe_roots` out, but this is not suggested. The current logged in user has to be memorized somewhere, we will use the ``'openid'`` key in the `session`. This can be implemented in a `before_request` function:: from flask import g, session @app.before_request def lookup_current_user(): g.user = None if 'openid' in session: openid = session['openid'] g.user = User.query.filter_by(openid=openid).first() This assumes the openid used for a user is stored in the user table itself. As you can see from the example above, we're using SQLAlchemy here, but feel free to use a different storage backend. It's just important that you can somehow map from openid URL to user. Next you need to define a login handling function. This function is a standard view function that is additionally decorated as :meth:`~OpenID.loginhandler`:: @app.route('/login', methods=['GET', 'POST']) @oid.loginhandler def login(): if g.user is not None: return redirect(oid.get_next_url()) if request.method == 'POST': openid = request.form.get('openid') if openid: return oid.try_login(openid, ask_for=['email', 'nickname'], ask_for_optional=['fullname']) return render_template('login.html', next=oid.get_next_url(), error=oid.fetch_error()) What's happening inside the login handler is that first we try to figure out if the user is already logged in. In that case we return to where we just came from (:meth:`~OpenID.get_next_url` can do that for us). When the data is submitted we get the openid the user entered and try to login with that information. Additionally we ask the openid provider for email, nickname and the user's full name, where we declare full name as optional. If that information is available, we can use it to simplify the account creation process in our application. The template also needs the URL we want to return to, because it has to forward that information in the form. If an error happened, :meth:`~OpenID.fetch_error` will return that error message for us. This is what a login template typically looks like: .. sourcecode:: html+jinja {% extends "layout.html" %} {% block title %}Sign in{% endblock %} {% block body %}

Sign in

{% if error %}

Error: {{ error }}

{% endif %}

OpenID:

{% endblock %} See how `error` and `next` are used. The name of the form field `next` is required, so don't change it. Responding to Successful Logins ------------------------------- Next we have to define a function that is called after the login was successful. The responsibility of that function is to remember the user that just logged in and to figure out if it's a new user to the system or one with an existing profile (if you want to use profiles). Such a function is decorated with :meth:`~OpenID.after_login` and must remember the user in the session and redirect to the proper page:: from flask import flash @oid.after_login def create_or_login(resp): session['openid'] = resp.identity_url user = User.query.filter_by(openid=resp.identity_url).first() if user is not None: flash(u'Successfully signed in') g.user = user return redirect(oid.get_next_url()) return redirect(url_for('create_profile', next=oid.get_next_url(), name=resp.fullname or resp.nickname, email=resp.email)) The `resp` object passed is a :class:`OpenIDResponse` object with all the information you might desire. As you can see, we memorize the user's openid and try to get the user with that OpenID from the database. If that fails we redirect the user to a page to create a new profile and also forward the name (or nickname if no name is provided) and the email address. Please keep in mind that an openid provider does not have to support these profile information and not every value you ask for will be there. If it's missing it will be `None`. Again make sure to not lose the information about the next URL. Creating a Profile ------------------ A typical page to create such a profile might look like this:: @app.route('/create-profile', methods=['GET', 'POST']) def create_profile(): if g.user is not None or 'openid' not in session: return redirect(url_for('index')) if request.method == 'POST': name = request.form['name'] email = request.form['email'] if not name: flash(u'Error: you have to provide a name') elif '@' not in email: flash(u'Error: you have to enter a valid email address') else: flash(u'Profile successfully created') db_session.add(User(name, email, session['openid'])) db_session.commit() return redirect(oid.get_next_url()) return render_template('create_profile.html', next=oid.get_next_url()) If you're using the same names for the URL parameters in the step before and in this form, you have nice looking and simple templates: .. sourcecode:: html+jinja {% extends "layout.html" %} {% block title %}Create Profile{% endblock %} {% block body %}

Create Profile

Hey! This is the first time you signed in on this website. In order to proceed we need a couple of more information from you:

Name:
E-Mail:

If you don't want to proceed, you can sign out again. {% endblock %} Logging Out ----------- The logout function is very simple, it just has to unset the openid from the session and redirect back to where the user was before:: @app.route('/logout') def logout(): session.pop('openid', None) flash(u'You were signed out') return redirect(oid.get_next_url()) Advanced usage -------------- Flask-OpenID can also work with any python-openid extension. To use this, pass a list of instantiated request openid.extension.Extension objects in the `extensions` field of :meth:`~OpenID.try_login`. The responses of these extensions are available during the :meth:`after_login` function, as entries in resp.extensions. Full Example ------------ To see the full code of that example, you can download the code `from github `_. Changes ------- 1.2 ``` - The safe_roots argument and URL security system was added. - The OpenID extensions system was added. 1.0 ``` - the OpenID object is not registered to an application which allows configuration values to be used and is also consistent with other Flask extensions. API References -------------- The full API reference: .. autoclass:: OpenID :members: .. autoclass:: OpenIDResponse :members: .. data:: COMMON_PROVIDERS a dictionary of common provider name -> login URL mappings. This can be used to implement "click button to login" functionality. Currently contains general purpose entrypoints for the following providers: ``google``, ``yahoo``, ``aol``, and ``steam``. .. _Flask: http://flask.pocoo.org/ .. _OpenID: http://openid.net/ .. _python-openid: http://openidenabled.com/python-openid/ Flask-OpenID-1.2.5/docs/_themes/0000775000175000017500000000000012575547273020706 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/docs/_themes/README0000664000175000017500000000210512464145171021550 0ustar puiterwijkpuiterwijk00000000000000Flask Sphinx Styles =================== This repository contains sphinx styles for Flask and Flask related projects. To use this style in your Sphinx documentation, follow this guide: 1. put this folder as _themes into your docs folder. Alternatively you can also use git submodules to check out the contents there. 2. add this to your conf.py: sys.path.append(os.path.abspath('_themes')) html_theme_path = ['_themes'] html_theme = 'flask' The following themes exist: - 'flask' - the standard flask documentation theme for large projects - 'flask_small' - small one-page theme. Intended to be used by very small addon libraries for flask. The following options exist for the flask_small theme: [options] index_logo = '' filename of a picture in _static to be used as replacement for the h1 in the index.rst file. index_logo_height = 120px height of the index logo github_fork = '' repository name on github for the "fork me" badge Flask-OpenID-1.2.5/docs/_themes/LICENSE0000664000175000017500000000337512464145171021707 0ustar puiterwijkpuiterwijk00000000000000Copyright (c) 2010 by Armin Ronacher. Some rights reserved. Redistribution and use in source and binary forms of the theme, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. We kindly ask you to only use these themes in an unmodified manner just for Flask and Flask-related products, not for unrelated projects. If you like the visual style and want to use it for your own projects, please consider making some larger changes to the themes (such as changing font faces, sizes, colors or margins). THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Flask-OpenID-1.2.5/docs/_themes/flask_small/0000775000175000017500000000000012575547273023176 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/docs/_themes/flask_small/layout.html0000664000175000017500000000125312464145171025366 0ustar puiterwijkpuiterwijk00000000000000{% extends "basic/layout.html" %} {% block header %} {{ super() }} {% if pagename == 'index' %}

{% endif %} {% endblock %} {% block footer %} {% if pagename == 'index' %}
{% endif %} {% endblock %} {# do not display relbars #} {% block relbar1 %}{% endblock %} {% block relbar2 %} {% if theme_github_fork %} Fork me on GitHub {% endif %} {% endblock %} {% block sidebar1 %}{% endblock %} {% block sidebar2 %}{% endblock %} Flask-OpenID-1.2.5/docs/_themes/flask_small/theme.conf0000664000175000017500000000027012464145171025132 0ustar puiterwijkpuiterwijk00000000000000[theme] inherit = basic stylesheet = flasky.css nosidebar = true pygments_style = flask_theme_support.FlaskyStyle [options] index_logo = '' index_logo_height = 120px github_fork = '' Flask-OpenID-1.2.5/docs/_themes/flask_small/static/0000775000175000017500000000000012575547273024465 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/docs/_themes/flask_small/static/flasky.css_t0000664000175000017500000001100112464145171026770 0ustar puiterwijkpuiterwijk00000000000000/* * flasky.css_t * ~~~~~~~~~~~~ * * Sphinx stylesheet -- flasky theme based on nature theme. * * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: 'Georgia', serif; font-size: 17px; color: #000; background: white; margin: 0; padding: 0; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 40px auto 0 auto; width: 700px; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 30px 30px; } img.floatingflask { padding: 0 0 10px 10px; float: right; } div.footer { text-align: right; color: #888; padding: 10px; font-size: 14px; width: 650px; margin: 0 auto 40px auto; } div.footer a { color: #888; text-decoration: underline; } div.related { line-height: 32px; color: #888; } div.related ul { padding: 0 0 0 10px; } div.related a { color: #444; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body { padding-bottom: 40px; /* saved for footer */ } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } {% if theme_index_logo %} div.indexwrapper h1 { text-indent: -999999px; background: url({{ theme_index_logo }}) no-repeat center center; height: {{ theme_index_logo_height }}; } {% endif %} div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: white; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #eaeaea; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { background: #fafafa; margin: 20px -30px; padding: 10px 30px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } div.admonition p.admonition-title { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight{ background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.85em; } img.screenshot { } tt.descname, tt.descclassname { font-size: 0.95em; } tt.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #eee; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td { padding: 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } pre { padding: 0; margin: 15px -30px; padding: 8px; line-height: 1.3em; padding: 7px 30px; background: #eee; border-radius: 2px; -moz-border-radius: 2px; -webkit-border-radius: 2px; } dl pre { margin-left: -60px; padding-left: 60px; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, a tt { background-color: #FBFBFB; } a:hover tt { background: #EEE; } Flask-OpenID-1.2.5/docs/_themes/flask/0000775000175000017500000000000012575547273022006 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/docs/_themes/flask/layout.html0000664000175000017500000000110612464145171024173 0ustar puiterwijkpuiterwijk00000000000000{%- extends "basic/layout.html" %} {%- block extrahead %} {{ super() }} {% if theme_touch_icon %} {% endif %} {% endblock %} {%- block relbar2 %}{% endblock %} {%- block footer %} {%- endblock %} Flask-OpenID-1.2.5/docs/_themes/flask/theme.conf0000664000175000017500000000017212464145171023743 0ustar puiterwijkpuiterwijk00000000000000[theme] inherit = basic stylesheet = flasky.css pygments_style = flask_theme_support.FlaskyStyle [options] touch_icon = Flask-OpenID-1.2.5/docs/_themes/flask/static/0000775000175000017500000000000012575547273023275 5ustar puiterwijkpuiterwijk00000000000000Flask-OpenID-1.2.5/docs/_themes/flask/static/flasky.css_t0000664000175000017500000001413112464145171025607 0ustar puiterwijkpuiterwijk00000000000000/* * flasky.css_t * ~~~~~~~~~~~~ * * :copyright: Copyright 2010 by Armin Ronacher. * :license: Flask Design License, see LICENSE for details. */ {% set page_width = '940px' %} {% set sidebar_width = '220px' %} @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: 'Georgia', serif; font-size: 17px; background-color: white; color: #000; margin: 0; padding: 0; } div.document { width: {{ page_width }}; margin: 30px auto 0 auto; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 {{ sidebar_width }}; } div.sphinxsidebar { width: {{ sidebar_width }}; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 0 30px; } img.floatingflask { padding: 0 0 10px 10px; float: right; } div.footer { width: {{ page_width }}; margin: 20px auto 30px auto; font-size: 14px; color: #888; text-align: right; } div.footer a { color: #888; } div.related { display: none; } div.sphinxsidebar a { color: #444; text-decoration: none; border-bottom: 1px dotted #999; } div.sphinxsidebar a:hover { border-bottom: 1px solid #999; } div.sphinxsidebar { font-size: 14px; line-height: 1.5; } div.sphinxsidebarwrapper { padding: 18px 10px; } div.sphinxsidebarwrapper p.logo { padding: 0 0 20px 0; margin: 0; text-align: center; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: 'Garamond', 'Georgia', serif; color: #444; font-size: 24px; font-weight: normal; margin: 0 0 5px 0; padding: 0; } div.sphinxsidebar h4 { font-size: 20px; } div.sphinxsidebar h3 a { color: #444; } div.sphinxsidebar p.logo a, div.sphinxsidebar h3 a, div.sphinxsidebar p.logo a:hover, div.sphinxsidebar h3 a:hover { border: none; } div.sphinxsidebar p { color: #555; margin: 10px 0; } div.sphinxsidebar ul { margin: 10px 0; padding: 0; color: #000; } div.sphinxsidebar input { border: 1px solid #ccc; font-family: 'Georgia', serif; font-size: 1em; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: #ddd; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #eaeaea; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { background: #fafafa; margin: 20px -30px; padding: 10px 30px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } div.admonition tt.xref, div.admonition a tt { border-bottom: 1px solid #fafafa; } dd div.admonition { margin-left: -60px; padding-left: 60px; } div.admonition p.admonition-title { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight { background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.9em; } img.screenshot { } tt.descname, tt.descclassname { font-size: 0.95em; } tt.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #eee; background: #fdfdfd; font-size: 0.9em; } table.footnote + table.footnote { margin-top: -15px; border-top: none; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td.label { width: 0px; padding: 0.3em 0 0.3em 0.5em; } table.footnote td { padding: 0.3em 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } blockquote { margin: 0 0 0 30px; padding: 0; } ul, ol { margin: 10px 0 10px 30px; padding: 0; } pre { background: #eee; padding: 7px 30px; margin: 15px -30px; line-height: 1.3em; } dl pre, blockquote pre, li pre { margin-left: -60px; padding-left: 60px; } dl dl pre { margin-left: -90px; padding-left: 90px; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, a tt { background-color: #FBFBFB; border-bottom: 1px solid white; } a.reference { text-decoration: none; border-bottom: 1px dotted #004B6B; } a.reference:hover { border-bottom: 1px solid #6D4100; } a.footnote-reference { text-decoration: none; font-size: 0.7em; vertical-align: top; border-bottom: 1px dotted #004B6B; } a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } a:hover tt { background: #EEE; } Flask-OpenID-1.2.5/docs/_themes/flask/static/small_flask.css0000664000175000017500000000172012464145171026263 0ustar puiterwijkpuiterwijk00000000000000/* * small_flask.css_t * ~~~~~~~~~~~~~~~~~ * * :copyright: Copyright 2010 by Armin Ronacher. * :license: Flask Design License, see LICENSE for details. */ body { margin: 0; padding: 20px 30px; } div.documentwrapper { float: none; background: white; } div.sphinxsidebar { display: block; float: none; width: 102.5%; margin: 50px -30px -20px -30px; padding: 10px 20px; background: #333; color: white; } div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, div.sphinxsidebar h3 a { color: white; } div.sphinxsidebar a { color: #aaa; } div.sphinxsidebar p.logo { display: none; } div.document { width: 100%; margin: 0; } div.related { display: block; margin: 0; padding: 10px 0 20px 0; } div.related ul, div.related ul li { margin: 0; padding: 0; } div.footer { display: none; } div.bodywrapper { margin: 0; } div.body { min-height: 0; padding: 0; } Flask-OpenID-1.2.5/docs/_themes/flask/relations.html0000664000175000017500000000111612464145171024657 0ustar puiterwijkpuiterwijk00000000000000

Related Topics

Flask-OpenID-1.2.5/docs/_themes/flask_theme_support.py0000664000175000017500000001141312464145171025322 0ustar puiterwijkpuiterwijk00000000000000# flasky extensions. flasky pygments style based on tango style from pygments.style import Style from pygments.token import Keyword, Name, Comment, String, Error, \ Number, Operator, Generic, Whitespace, Punctuation, Other, Literal class FlaskyStyle(Style): background_color = "#f8f8f8" default_style = "" styles = { # No corresponding class for the following: #Text: "", # class: '' Whitespace: "underline #f8f8f8", # class: 'w' Error: "#a40000 border:#ef2929", # class: 'err' Other: "#000000", # class 'x' Comment: "italic #8f5902", # class: 'c' Comment.Preproc: "noitalic", # class: 'cp' Keyword: "bold #004461", # class: 'k' Keyword.Constant: "bold #004461", # class: 'kc' Keyword.Declaration: "bold #004461", # class: 'kd' Keyword.Namespace: "bold #004461", # class: 'kn' Keyword.Pseudo: "bold #004461", # class: 'kp' Keyword.Reserved: "bold #004461", # class: 'kr' Keyword.Type: "bold #004461", # class: 'kt' Operator: "#582800", # class: 'o' Operator.Word: "bold #004461", # class: 'ow' - like keywords Punctuation: "bold #000000", # class: 'p' # because special names such as Name.Class, Name.Function, etc. # are not recognized as such later in the parsing, we choose them # to look the same as ordinary variables. Name: "#000000", # class: 'n' Name.Attribute: "#c4a000", # class: 'na' - to be revised Name.Builtin: "#004461", # class: 'nb' Name.Builtin.Pseudo: "#3465a4", # class: 'bp' Name.Class: "#000000", # class: 'nc' - to be revised Name.Constant: "#000000", # class: 'no' - to be revised Name.Decorator: "#888", # class: 'nd' - to be revised Name.Entity: "#ce5c00", # class: 'ni' Name.Exception: "bold #cc0000", # class: 'ne' Name.Function: "#000000", # class: 'nf' Name.Property: "#000000", # class: 'py' Name.Label: "#f57900", # class: 'nl' Name.Namespace: "#000000", # class: 'nn' - to be revised Name.Other: "#000000", # class: 'nx' Name.Tag: "bold #004461", # class: 'nt' - like a keyword Name.Variable: "#000000", # class: 'nv' - to be revised Name.Variable.Class: "#000000", # class: 'vc' - to be revised Name.Variable.Global: "#000000", # class: 'vg' - to be revised Name.Variable.Instance: "#000000", # class: 'vi' - to be revised Number: "#990000", # class: 'm' Literal: "#000000", # class: 'l' Literal.Date: "#000000", # class: 'ld' String: "#4e9a06", # class: 's' String.Backtick: "#4e9a06", # class: 'sb' String.Char: "#4e9a06", # class: 'sc' String.Doc: "italic #8f5902", # class: 'sd' - like a comment String.Double: "#4e9a06", # class: 's2' String.Escape: "#4e9a06", # class: 'se' String.Heredoc: "#4e9a06", # class: 'sh' String.Interpol: "#4e9a06", # class: 'si' String.Other: "#4e9a06", # class: 'sx' String.Regex: "#4e9a06", # class: 'sr' String.Single: "#4e9a06", # class: 's1' String.Symbol: "#4e9a06", # class: 'ss' Generic: "#000000", # class: 'g' Generic.Deleted: "#a40000", # class: 'gd' Generic.Emph: "italic #000000", # class: 'ge' Generic.Error: "#ef2929", # class: 'gr' Generic.Heading: "bold #000080", # class: 'gh' Generic.Inserted: "#00A000", # class: 'gi' Generic.Output: "#888", # class: 'go' Generic.Prompt: "#745334", # class: 'gp' Generic.Strong: "bold #000000", # class: 'gs' Generic.Subheading: "bold #800080", # class: 'gu' Generic.Traceback: "bold #a40000", # class: 'gt' } Flask-OpenID-1.2.5/PKG-INFO0000664000175000017500000000206412575547273017431 0ustar puiterwijkpuiterwijk00000000000000Metadata-Version: 1.1 Name: Flask-OpenID Version: 1.2.5 Summary: OpenID support for Flask Home-page: http://github.com/mitsuhiko/flask-openid/ Author: Armin Ronacher, Patrick Uiterwijk Author-email: armin.ronacher@active-4.com, puiterwijk@redhat.com License: BSD Description: Flask-OpenID ============ Adds OpenID support to Flask. Links: * `Flask-OpenID Documentation `_ * `Flask `_ * `development version `_ Platform: any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules