diff options
author | rcritten <devnull@localhost> | 2007-09-10 16:33:01 -0400 |
---|---|---|
committer | rcritten <devnull@localhost> | 2007-09-10 16:33:01 -0400 |
commit | 182fbe30945a8de005f00b460968dca7973342fb (patch) | |
tree | 644f8efd633cbb41a387fb33e3deab8de20718b5 /ipa-server/ipa-gui | |
parent | 37d10e0c51dc289d815c05cd4d051e9d4120399e (diff) | |
download | freeipa-182fbe30945a8de005f00b460968dca7973342fb.tar.gz freeipa-182fbe30945a8de005f00b460968dca7973342fb.tar.xz freeipa-182fbe30945a8de005f00b460968dca7973342fb.zip |
Enable mod_proxy to sit in front of TurboGears and pass along the
kerberos principal name
Add an identity an visit class to TurboGears that can handle the user
without requiring a database
Update the UI to show the user correctly.
Note that this is currently disabled. It is hardcoded to always return the
principal test@FREEIPA.ORG in proxyprovider.py
It doesn't handle an unauthorized request because that can never happen.
Diffstat (limited to 'ipa-server/ipa-gui')
-rw-r--r-- | ipa-server/ipa-gui/dev.cfg | 13 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt | 7 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipa_gui.egg-info/entry_points.txt | 6 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/controllers.py | 23 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/proxyprovider.py | 118 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/proxyvisit.py | 25 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/templates/master.kid | 19 | ||||
-rw-r--r-- | ipa-server/ipa-gui/setup.py | 6 |
8 files changed, 205 insertions, 12 deletions
diff --git a/ipa-server/ipa-gui/dev.cfg b/ipa-server/ipa-gui/dev.cfg index 7bb0fd8c4..7cc2441d0 100644 --- a/ipa-server/ipa-gui/dev.cfg +++ b/ipa-server/ipa-gui/dev.cfg @@ -13,8 +13,19 @@ # If you have sqlite, here's a simple default to get you started # in development -sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite" +# sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite" +# Our our sqlobject-derived proxy provider +identity.provider='proxyprovider' + +# the first thing checked on any request. We want to short-circuit this +# as early as possible +identity.source = 'visit' + +# Turn on identity and visit (visit is required for identity) +identity.on=True +visit.on=True +visit.manager='proxyvisit' # if you are using a database or table type without transactions # (MySQL default, for example), you should turn off transactions diff --git a/ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt b/ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt index 49b7ce44d..3bd848243 100644 --- a/ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt +++ b/ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt @@ -4,6 +4,7 @@ start-ipagui.py ipa_gui.egg-info/PKG-INFO ipa_gui.egg-info/SOURCES.txt ipa_gui.egg-info/dependency_links.txt +ipa_gui.egg-info/entry_points.txt ipa_gui.egg-info/not-zip-safe ipa_gui.egg-info/paster_plugins.txt ipa_gui.egg-info/requires.txt @@ -13,8 +14,14 @@ ipagui/__init__.py ipagui/controllers.py ipagui/json.py ipagui/model.py +ipagui/proxyprovider.py +ipagui/proxyvisit.py ipagui/release.py ipagui/config/__init__.py +ipagui/forms/__init__.py +ipagui/forms/user.py +ipagui/helpers/__init__.py +ipagui/helpers/userhelper.py ipagui/templates/__init__.py ipagui/tests/__init__.py ipagui/tests/test_controllers.py diff --git a/ipa-server/ipa-gui/ipa_gui.egg-info/entry_points.txt b/ipa-server/ipa-gui/ipa_gui.egg-info/entry_points.txt new file mode 100644 index 000000000..22c35bfdb --- /dev/null +++ b/ipa-server/ipa-gui/ipa_gui.egg-info/entry_points.txt @@ -0,0 +1,6 @@ + + [turbogears.identity.provider] + proxyprovider = ipagui.proxyprovider:ProxyIdentityProvider + + [turbogears.visit.manager] + proxyvisit = ipagui.proxyvisit:ProxyVisitManager diff --git a/ipa-server/ipa-gui/ipagui/controllers.py b/ipa-server/ipa-gui/ipagui/controllers.py index acbc48185..a07555257 100644 --- a/ipa-server/ipa-gui/ipagui/controllers.py +++ b/ipa-server/ipa-gui/ipagui/controllers.py @@ -8,6 +8,7 @@ from turbogears import controllers, expose, flash from turbogears import validators, validate from turbogears import widgets, paginate from turbogears import error_handler +from turbogears import identity # from model import * # import logging # log = logging.getLogger("ipagui.controllers") @@ -27,7 +28,6 @@ user_edit_form = forms.user.UserEditForm() password_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" client = ipa.ipaclient.IPAClient(True) -client.set_principal("test@FREEIPA.ORG") user_fields = ['*', 'nsAccountLock'] @@ -45,10 +45,12 @@ def utf8_encode(value): class Root(controllers.RootController): @expose(template="ipagui.templates.welcome") + @identity.require(identity.not_anonymous()) def index(self): return dict() @expose() + @identity.require(identity.not_anonymous()) def topsearch(self, **kw): if kw.get('searchtype') == "Users": return self.userlist(uid=kw.get('searchvalue')) @@ -62,6 +64,7 @@ class Root(controllers.RootController): ######## @expose("ipagui.templates.usernew") + @identity.require(identity.not_anonymous()) def usernew(self, tg_errors=None): """Displays the new user form""" if tg_errors: @@ -70,9 +73,11 @@ class Root(controllers.RootController): return dict(form=user_new_form) @expose() + @identity.require(identity.not_anonymous()) def usercreate(self, **kw): """Creates a new user""" restrict_post() + client.set_principal(identity.current.user_name) if kw.get('submit') == 'Cancel': turbogears.flash("Add user cancelled") raise turbogears.redirect('/userlist') @@ -104,11 +109,13 @@ class Root(controllers.RootController): @expose("ipagui.templates.useredit") + @identity.require(identity.not_anonymous()) def useredit(self, uid, tg_errors=None): """Displays the edit user form""" if tg_errors: turbogears.flash("There was a problem with the form!") + client.set_principal(identity.current.user_name) user = client.get_user_by_uid(uid, user_fields) user_dict = user.toDict() # Edit shouldn't fill in the password field. @@ -121,9 +128,11 @@ class Root(controllers.RootController): return dict(form=user_edit_form, user=user_dict) @expose() + @identity.require(identity.not_anonymous()) def userupdate(self, **kw): """Updates an existing user""" restrict_post() + client.set_principal(identity.current.user_name) if kw.get('submit') == 'Cancel Edit': turbogears.flash("Edit user cancelled") raise turbogears.redirect('/usershow', uid=kw.get('uid')) @@ -169,8 +178,10 @@ class Root(controllers.RootController): @expose("ipagui.templates.userlist") + @identity.require(identity.not_anonymous()) def userlist(self, **kw): """Retrieve a list of all users and display them in one huge list""" + client.set_principal(identity.current.user_name) users = None counter = 0 uid = kw.get('uid') @@ -190,8 +201,10 @@ class Root(controllers.RootController): @expose("ipagui.templates.usershow") + @identity.require(identity.not_anonymous()) def usershow(self, uid): """Retrieve a single user for display""" + client.set_principal(identity.current.user_name) try: user = client.get_user_by_uid(uid, user_fields) return dict(user=user.toDict(), fields=forms.user.UserFields()) @@ -200,10 +213,12 @@ class Root(controllers.RootController): raise turbogears.redirect("/") @validate(form=user_new_form) + @identity.require(identity.not_anonymous()) def usercreatevalidate(self, tg_errors=None, **kw): return tg_errors, kw @validate(form=user_edit_form) + @identity.require(identity.not_anonymous()) def userupdatevalidate(self, tg_errors=None, **kw): return tg_errors, kw @@ -222,10 +237,12 @@ class Root(controllers.RootController): return password @expose() + @identity.require(identity.not_anonymous()) def suggest_uid(self, givenname, sn): if (len(givenname) == 0) or (len(sn) == 0): return "" + client.set_principal(identity.current.user_name) givenname = givenname.lower() sn = sn.lower() @@ -309,7 +326,9 @@ class Root(controllers.RootController): ######### @expose("ipagui.templates.groupindex") + @identity.require(identity.not_anonymous()) def groupindex(self, tg_errors=None): + client.set_principal(identity.current.user_name) return dict() @@ -318,5 +337,7 @@ class Root(controllers.RootController): ############ @expose("ipagui.templates.resindex") + @identity.require(identity.not_anonymous()) def resindex(self, tg_errors=None): + client.set_principal(identity.current.user_name) return dict() diff --git a/ipa-server/ipa-gui/ipagui/proxyprovider.py b/ipa-server/ipa-gui/ipagui/proxyprovider.py new file mode 100644 index 000000000..125198806 --- /dev/null +++ b/ipa-server/ipa-gui/ipagui/proxyprovider.py @@ -0,0 +1,118 @@ +from turbogears.identity.soprovider import * +from turbogears.identity.visitor import * +import logging + +log = logging.getLogger("turbogears.identity") + +class IPA_User(object): + ''' + Shell of a User definition. We don't really need much here. + ''' + + def __init__(self, user_name): + self.user_name = user_name + self.display_name = user_name + self.permissions = None + self.groups = None + return + +class ProxyIdentity(object): + def __init__(self, visit_key, user=None): + if user: + self._user= user + self.visit_key= visit_key + + def _get_user(self): + try: + return self._user + except AttributeError: + # User hasn't already been set + return None + user= property(_get_user) + + def _get_user_name(self): + if not self.user: + return None + return self.user.user_name + user_name= property(_get_user_name) + + def _get_name(self): + if not self.user: + return None + return self.user.name + user_name= property(_get_name) + + def _get_anonymous(self): + return not self.user + anonymous= property(_get_anonymous) + + def _get_permissions(self): + try: + return self._permissions + except AttributeError: + # Permissions haven't been computed yet + return None + permissions= property(_get_permissions) + + def _get_groups(self): + try: + return self._groups + except AttributeError: + # Groups haven't been computed yet + return None + groups= property(_get_groups) + + def logout(self): + ''' + Remove the link between this identity and the visit. + ''' + # Clear the current identity + anon= ProxyObjectIdentity(None,None) + #XXX if user is None anonymous will be true, no need to set attr. + #anon.anonymous= True + identity.set_current_identity( anon ) + +class ProxyIdentityProvider(SqlObjectIdentityProvider): + ''' + IdentityProvider that uses REMOTE_USER from Apache + ''' + def __init__(self): + super(ProxyIdentityProvider, self).__init__() + get = turbogears.config.get + # We can get any config variables here + log.info( "Proxy Identity starting" ) + + def create_provider_model(self): + pass + + def validate_identity(self, user_name, password, visit_key): + user = IPA_User(user_name) + log.debug( "validate_identity %s" % user_name) + + return ProxyIdentity(visit_key, user) + + def validate_password(self, user, user_name, password): + '''Validation has already occurred in the proxy''' + return True + + def load_identity(self, visit_key): + try: +# user_name= cherrypy.request.headers['X-FORWARDED-USER'] + user_name= "test@FREEIPA.ORG" + except KeyError: + return None + set_login_attempted( True ) + return self.validate_identity( user_name, None, visit_key ) + + def anonymous_identity( self ): + ''' + This shouldn't ever happen in IPA but including it to include the + entire identity API. + ''' + return ProxyIdentity( None ) + + def authenticated_identity(self, user): + ''' + Constructs Identity object for user that has no associated visit_key. + ''' + return ProxyIdentity(None, user) diff --git a/ipa-server/ipa-gui/ipagui/proxyvisit.py b/ipa-server/ipa-gui/ipagui/proxyvisit.py new file mode 100644 index 000000000..1fde3902e --- /dev/null +++ b/ipa-server/ipa-gui/ipagui/proxyvisit.py @@ -0,0 +1,25 @@ +from turbogears.visit.api import BaseVisitManager, Visit +from turbogears import config + +import logging + +log = logging.getLogger("turbogears.visit.proxyvisit") + +class ProxyVisitManager(BaseVisitManager): + """Virtually empty class just so can avoid saving this stuff in a + database.""" + def __init__(self, timeout): + super(ProxyVisitManager,self).__init__(timeout) + return + + def create_model(self): + return + + def new_visit_with_key(self, visit_key): + return Visit(visit_key, True) + + def visit_for_key(self, visit_key): + return Visit(visit_key, False) + + def update_queued_visits(self, queue): + return None diff --git a/ipa-server/ipa-gui/ipagui/templates/master.kid b/ipa-server/ipa-gui/ipagui/templates/master.kid index 8abe24bac..2d3a35f22 100644 --- a/ipa-server/ipa-gui/ipagui/templates/master.kid +++ b/ipa-server/ipa-gui/ipagui/templates/master.kid @@ -14,15 +14,6 @@ </head> <body py:match="item.tag=='{http://www.w3.org/1999/xhtml}body'" py:attrs="item.items()"> - <div py:if="tg.config('identity.on') and not defined('logging_in')" id="pageLogin"> - <span py:if="tg.identity.anonymous"> - <a href="${tg.url('/login')}">Login</a> - </span> - <span py:if="not tg.identity.anonymous"> - Welcome ${tg.identity.user.display_name}. - <a href="${tg.url('/logout')}">Logout</a> - </span> - </div> <div id="header"> <div id="logo"> @@ -33,7 +24,15 @@ </div> <div id="headerinfo"> <div id="login"> - Logged in as: ace + <div py:if="tg.config('identity.on') and not defined('logging_in')" id="pageLogin"> + <span py:if="tg.identity.anonymous"> + <a href="${tg.url('/login')}">Login</a> + </span> + <span py:if="not tg.identity.anonymous"> + Logged in as: ${tg.identity.user.display_name} + </span> + </div> + </div> <div id="topsearch"> <form action="${tg.url('/topsearch')}" method="post"> diff --git a/ipa-server/ipa-gui/setup.py b/ipa-server/ipa-gui/setup.py index 371325f6a..123817999 100644 --- a/ipa-server/ipa-gui/setup.py +++ b/ipa-server/ipa-gui/setup.py @@ -58,5 +58,11 @@ setup( # 'Framework :: TurboGears :: Widgets', ], test_suite = 'nose.collector', + entry_points = """ + [turbogears.identity.provider] + proxyprovider = ipagui.proxyprovider:ProxyIdentityProvider + [turbogears.visit.manager] + proxyvisit = ipagui.proxyvisit:ProxyVisitManager + """, ) |