Source code for authomatic.extras.gae

"""
|gae| Extras
------------

Utilities you can use when using this library on |gae|_.
"""

from authomatic import exceptions
from authomatic.extras import interfaces
from google.appengine.ext import ndb
from webapp2_extras import sessions
import os


__all__ = ['ndb_config']


class GAEError(exceptions.BaseError):
    pass


[docs]class Webapp2Session(interfaces.BaseSession): def __init__(self, handler, session=None, secret=None, cookie_name='webapp2authomatic', backend='memcache', config=None): """ A simple wrapper for |webapp2|_ sessions. If you provide a session it wrapps it and adds the :meth:`.save` method. If you don't provide a session it creates a new one but you must provide the :data:`.secret`. For more about |webapp2| sessions see: `http://webapp-improved.appspot.com/api/webapp2_extras/sessions.html`_. .. warning:: Do not use the ``'securecookie'`` backend with :class:`.providers.OpenID` provider. The `python-openid`_ library saves **non json serializable** objects to session which the ``'securecookie'`` backend cannot cope with. :param handler: A :class:`webapp2.RequestHandler` instance. :param session: A :class:`webapp2_extras.session.SessionDict` instance. :param str secret: The session secret. :param str cookie_name: The name of the session kookie. :param backend: The session backend. One of ``'memcache'`` or ``'datastore'``. :param config: The session config. """ self.handler = handler if session is None: if not secret: raise GAEError('Either session or secret must be specified!') else: # Create new session. cfg = config or dict(secret_key=secret, cookie_name=cookie_name) session_store = sessions.SessionStore(handler.request, cfg) self.session_dict = session_store.get_session(backend=backend) else: # Use supplied session. self.session_dict = session def save(self): return self.session_dict.container.save_session(self.handler.response) def __setitem__(self, key, value): return self.session_dict.__setitem__(key, value) def __getitem__(self, key): return self.session_dict.__getitem__(key) def __delitem__(self, key): return self.session_dict.__delitem__(key) def get(self, key): return self.session_dict.get(key)
class NDBConfig(ndb.Model): """ |gae| `NDB <https://developers.google.com/appengine/docs/python/ndb/>`_ based :doc:`config`. """ provider_name = ndb.StringProperty( ) class_ = ndb.StringProperty() # AuthorisationProvider short_name = ndb.IntegerProperty() consumer_key = ndb.StringProperty() consumer_secret = ndb.StringProperty() # OAuth2 scope = ndb.StringProperty() # AuthenticationProvider identifier_param = ndb.StringProperty() # OpenID use_realm = ndb.BooleanProperty(default=True) realm_body = ndb.StringProperty() realm_param = ndb.StringProperty() xrds_param = ndb.StringProperty() sreg = ndb.StringProperty() sreg_required = ndb.StringProperty() ax = ndb.StringProperty() ax_required = ndb.StringProperty() pape = ndb.StringProperty() @classmethod def get(cls, key, default=None): """ Resembles the dict.get(key[, default=None]) method Returns a provider config dictionary """ result = cls.query(cls.provider_name == key).get() if result: result_dict = result.to_dict() for i in ('scope', 'sreg', 'sreg_required', 'ax', 'ax_required', 'pape', ): prop = result_dict.get(i) if prop: result_dict[i] = [s.strip() for s in prop.split(',')] else: result_dict[i] = None return result_dict else: return default @classmethod def values(cls): # get all items results = cls.query().fetch() # return list of dictionaries return [result.to_dict() for result in results] @classmethod def initialize(cls): """ Creates an Example entity if the model is empty """ if not len(cls.query().fetch()): example = cls.get_or_insert('Example') example.class_ = 'Provider class e.g. "authomatic.providers.oauth2.Facebook".' example.provider_name = 'Your custom provider name e.g. "fb".' # TODO: Implement all new arguments including openid store. # AuthorisationProvider example.consumer_key = 'Consumer key.' example.consumer_secret = 'Consumer secret' example.short_name = 1 # OAuth2 example.scope = 'coma, separated, list, of, scopes' # AuthenticationProvider example.identifier_param = 'User identifier to authenticate e.g. "me.yahoo.com".' # OpenID example.use_realm = True example.realm_body = 'Contents of the HTML body tag of the realm.' example.realm_param = 'Name of the query parameter to be used to serve the realm (leave empty for default).' example.xrds_param = ' The name of the query parameter to be used to serve the XRDS document (leave empty for default).' example.sreg = 'list, of, strings, of, optional, SREG, fields, (leave empty for defaults)' example.sreg_required = 'list, of, strings, of, required, SREG, fields, (leave empty for defaults)' example.ax = 'list, of, strings, of, optional, AX, schemas, (leave empty for defaults)' example.ax_required = 'list, of, strings, of, required, AX, schemas, (leave empty for defaults)' example.pape = 'list, of, strings, of, optional, PAPE, policies, (leave empty for defaults)' example.put() url = '{}://{}/_ah/admin/datastore?kind={}'.format(os.environ.get('wsgi.url_scheme'), os.environ.get('HTTP_HOST'), cls.__name__) raise GAEError('A NDBConfig data model was created! ' + \ 'Go to {} and populate it with data!'.format(url))
[docs]def ndb_config(): """ Allows you to have a **datastore** :doc:`config` instead of a hardcoded one. This function creates an **"Example"** entity of kind **"NDBConfig"** in the datastore if the model is empty and raises and error to inform you that you should populate the model with data. .. note:: The *Datastore Viewer* in the ``_ah/admin/`` wont let you add properties to a model if there is not an entity with that property allready. Therefore it is a good idea to keep the **"Example"** entity (which has all possible properties set) in the datastore. :raises: :exc:`.GAEError` :returns: :class:`.NDBConfig` """ NDBConfig.initialize() return NDBConfig
Fork me on GitHub