+
+class LoginHelper(Log):
+
+ """Common code supporing login operations.
+
+ Ipsilon can authtenticate a user by itself via it's own login
+ handlers (classes derived from `LoginManager`) or it can
+ capitalize on the authentication provided by the container Ipsilon
+ is running in (currently WSGI inside Apache). We refer to the
+ later as "external authentication" because it occurs outside of
+ Ipsilon. However in both cases there is a common need to execute
+ the same code irregardless of where the authntication
+ occurred. This class serves that purpose.
+ """
+
+ def get_external_auth_info(self):
+ """Return the username and auth type for external authentication.
+
+ If the container Ipsilon is running inside of has already
+ authenticated the user prior to reaching one of our endpoints
+ return the username and the name of authenticaion method
+ used. In Apache this will be REMOTE_USER and AUTH_TYPE.
+
+ The returned auth_type will be prefixed with the string
+ "external:" to clearly distinguish between the same method
+ being used internally by Ipsilon from the same method used by
+ the container hosting Ipsilon. The returned auth_type string
+ will be lower case.
+
+ If there was no external authentication both username and
+ auth_type will be None. It is possible for a username to be
+ returned without knowing the auth_type.
+
+ :return: tuple of (username, auth_type)
+ """
+
+ auth_type = None
+ username = cherrypy.request.login
+ if username:
+ auth_type = cherrypy.request.wsgi_environ.get('AUTH_TYPE')
+ if auth_type:
+ auth_type = 'external:%s' % (auth_type.lower())
+
+ self.debug("get_external_auth_info: username=%s auth_type=%s" % (
+ username, auth_type))
+
+ return username, auth_type
+
+ def initialize_login_session(self, username, info=None,
+ auth_type=None, userdata=None):
+ """Establish a login session for a user.
+
+ Builds a `UserSession` object and bind attributes associated
+ with the user to the session.
+
+ User attributes derive from two sources, the `Info` object
+ passed as the info parameter and the userdata dict. The `Info`
+ object encapsulates the info plugins run by Ipsilon. The
+ userdata dict is additional information typically derived
+ during authentication.
+
+ The `Info` derived attributes are merged with the userdata
+ attributes to form one set of user attributes. The user
+ attributes are checked for consistenccy. Additional attrbutes
+ may be synthesized and added to the user attributes. The final
+ set of user attributes is then bound to the returned
+ `UserSession` object.
+
+ :param username: The username bound to the identity principal
+ :param info: A `Info` object providing user attributes
+ :param auth_type: Authenication method name
+ :param userdata: Dict of additional user attributes
+
+ :return: `UserSession` object
+ """
+
+ session = UserSession()
+
+ # merge attributes from login plugin and info plugin
+ if info:
+ infoattrs = info.get_user_attrs(username)
+ else:
+ infoattrs = dict()
+
+ if userdata is None:
+ userdata = dict()
+
+ if '_groups' in infoattrs:
+ userdata['_groups'] = list(set(userdata.get('_groups', []) +
+ infoattrs['_groups']))
+ del infoattrs['_groups']
+
+ if '_extras' in infoattrs:
+ userdata['_extras'] = userdata.get('_extras', {})
+ userdata['_extras'].update(infoattrs['_extras'])
+ del infoattrs['_extras']
+
+ userdata.update(infoattrs)
+
+ self.debug("User %s attributes: %s" % (username, repr(userdata)))
+
+ if auth_type:
+ if userdata:
+ userdata.update({'_auth_type': auth_type})
+ else:
+ userdata = {'_auth_type': auth_type}
+
+ # create session login including all the userdata just gathered
+ session.login(username, userdata)
+
+ return session
+
+
+class LoginManagerBase(ConfigHelper, PluginObject, LoginHelper):
+
+ def __init__(self, *args):
+ ConfigHelper.__init__(self)
+ PluginObject.__init__(self, *args)
+ self._root = None
+ self._site = None