Implement change registration
[cascardo/ipsilon.git] / ipsilon / login / common.py
index 60f6df1..db71fb0 100644 (file)
@@ -1,24 +1,10 @@
-# Copyright (C) 2013  Simo Sorce <simo@redhat.com>
-#
-# see file 'COPYING' for use and warranty information
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# Copyright (C) 2013 Ipsilon project Contributors, for license see COPYING
 
 from ipsilon.util.page import Page
 from ipsilon.util.user import UserSession
 from ipsilon.util.plugin import PluginInstaller, PluginLoader
-from ipsilon.util.plugin import PluginObject, PluginConfig
+from ipsilon.util.plugin import PluginObject
+from ipsilon.util.config import ConfigHelper
 from ipsilon.info.common import Info
 from ipsilon.util.cookies import SecureCookie
 import cherrypy
@@ -27,10 +13,10 @@ import cherrypy
 USERNAME_COOKIE = 'ipsilon_default_username'
 
 
-class LoginManagerBase(PluginConfig, PluginObject):
+class LoginManagerBase(ConfigHelper, PluginObject):
 
     def __init__(self, *args):
-        PluginConfig.__init__(self)
+        ConfigHelper.__init__(self)
         PluginObject.__init__(self, *args)
         self._root = None
         self._site = None
@@ -122,6 +108,9 @@ class LoginManagerBase(PluginConfig, PluginObject):
 
         raise cherrypy.HTTPRedirect(transdata['login_return'])
 
+    def set_auth_error(self):
+        cherrypy.response.status = 401
+
     def get_tree(self, site):
         raise NotImplementedError
 
@@ -138,6 +127,19 @@ class LoginManagerBase(PluginConfig, PluginObject):
         except (ValueError, IndexError):
             return None
 
+    def other_login_stacks(self):
+        plugins = self._site[FACILITY]
+        stack = list()
+        try:
+            idx = plugins.enabled.index(self.name)
+        except (ValueError, IndexError):
+            idx = None
+        for i in range(0, len(plugins.enabled)):
+            if i == idx:
+                continue
+            stack.append(plugins.available[plugins.enabled[i]])
+        return stack
+
     def on_enable(self):
 
         # and add self to the root
@@ -168,7 +170,6 @@ class LoginFormBase(LoginPageBase):
 
     def GET(self, *args, **kwargs):
         context = self.create_tmpl_context()
-        # pylint: disable=star-args
         return self._template(self.formtemplate, **context)
 
     def root(self, *args, **kwargs):
@@ -178,11 +179,14 @@ class LoginFormBase(LoginPageBase):
             return op(*args, **kwargs)
 
     def create_tmpl_context(self, **kwargs):
-        next_url = None
-        next_login = self.lm.next_login()
-        if next_login:
-            next_url = '%s?%s' % (next_login.path,
-                                  self.trans.get_GET_arg())
+        other_stacks = None
+        other_login_stacks = self.lm.other_login_stacks()
+        if other_login_stacks:
+            other_stacks = list()
+            for ls in other_login_stacks:
+                url = '%s?%s' % (ls.path, self.trans.get_GET_arg())
+                name = ls.name
+                other_stacks.append({'url': url, 'name': name})
 
         cookie = SecureCookie(USERNAME_COOKIE)
         cookie.receive()
@@ -206,7 +210,7 @@ class LoginFormBase(LoginPageBase):
             "username_text": self.lm.username_text,
             "password_text": self.lm.password_text,
             "description": self.lm.help_text,
-            "next_url": next_url,
+            "other_stacks": other_stacks,
             "username": username,
             "login_target": target,
             "cancel_url": '%s/login/cancel?%s' % (self.basepath,
@@ -235,14 +239,14 @@ class Login(Page):
         self._site[FACILITY] = plugins
 
         available = plugins.available.keys()
-        self._debug('Available login managers: %s' % str(available))
+        self.debug('Available login managers: %s' % str(available))
 
         for item in plugins.available:
             plugin = plugins.available[item]
             plugin.register(self, self._site)
 
         for item in plugins.enabled:
-            self._debug('Login plugin in enabled list: %s' % item)
+            self.debug('Login plugin in enabled list: %s' % item)
             if item not in plugins.available:
                 continue
             plugins.available[item].enable()
@@ -270,11 +274,28 @@ class Login(Page):
 
 
 class Logout(Page):
+    def __init__(self, *args, **kwargs):
+        super(Logout, self).__init__(*args, **kwargs)
+        self.handlers = {}
 
     def root(self, *args, **kwargs):
-        UserSession().logout(self.user)
+        us = UserSession()
+
+        for provider in self.handlers:
+            self.debug("Calling logout for provider %s" % provider)
+            obj = self.handlers[provider]
+            obj()
+
+        us.logout(self.user)
         return self._template('logout.html', title='Logout')
 
+    def add_handler(self, provider, handler):
+        """
+        Providers can register a logout handler here that is called
+        when the IdP logout link is accessed.
+        """
+        self.handlers[provider] = handler
+
 
 class Cancel(Page):
 
@@ -301,13 +322,16 @@ class LoginManagerInstaller(object):
         self.ptype = 'login'
         self.name = None
 
-    def unconfigure(self, opts):
+    def unconfigure(self, opts, changes):
         return
 
     def install_args(self, group):
         raise NotImplementedError
 
-    def configure(self, opts):
+    def validate_args(self, args):
+        return
+
+    def configure(self, opts, changes):
         raise NotImplementedError