From 14e8ecd7cf8ea8d342eac5c4c66b764b3a8e2dbb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 2 Sep 2014 17:41:07 -0400 Subject: [PATCH] Add Info providers Admin pages Signed-off-by: Simo Sorce Reviewed-by: Patrick Uiterwijk --- ipsilon/admin/common.py | 3 +- ipsilon/admin/info.py | 142 +++++++++++++++++++++++++++++ ipsilon/info/common.py | 28 +++++- ipsilon/login/common.py | 2 +- ipsilon/root.py | 2 + templates/admin/info.html | 31 +++++++ templates/admin/info_order.html | 25 +++++ templates/admin/plugin_config.html | 2 +- 8 files changed, 229 insertions(+), 6 deletions(-) create mode 100755 ipsilon/admin/info.py create mode 100644 templates/admin/info.html create mode 100644 templates/admin/info_order.html diff --git a/ipsilon/admin/common.py b/ipsilon/admin/common.py index d2ef3cf..2c8ff89 100755 --- a/ipsilon/admin/common.py +++ b/ipsilon/admin/common.py @@ -32,6 +32,7 @@ class AdminPluginPage(Page): self.url = '%s/%s' % (parent.url, obj.name) self.facility = parent.facility self.menu = [parent] + self.back = parent.url # Get the defaults self.plugin_config = obj.get_config_desc() @@ -61,7 +62,7 @@ class AdminPluginPage(Page): return self._template('admin/plugin_config.html', title=self.title, name='admin_%s_%s_form' % (self.facility, self._obj.name), - menu=self.menu, action=self.url, + menu=self.menu, action=self.url, back=self.back, options_order=self.options_order, options=self.plugin_config) diff --git a/ipsilon/admin/info.py b/ipsilon/admin/info.py new file mode 100755 index 0000000..4154339 --- /dev/null +++ b/ipsilon/admin/info.py @@ -0,0 +1,142 @@ +#!/usr/bin/python +# +# Copyright (C) 2014 Ipsilon Contributors see COPYING for license + +import cherrypy +from ipsilon.util.page import Page +from ipsilon.util.page import admin_protect +from ipsilon.util.plugin import PluginObject +from ipsilon.admin.common import AdminPluginPage +from ipsilon.info.common import FACILITY + + +class InfoPluginsOrder(Page): + + def __init__(self, site, parent): + super(InfoPluginsOrder, self).__init__(site, form=True) + self.url = '%s/order' % parent.url + self.menu = [parent] + + @admin_protect + def GET(self, *args, **kwargs): + opts = [p.name for p in self._site[FACILITY]['enabled']] + return self._template('admin/info_order.html', + title='info plugins order', + name='admin_info_order_form', + menu=self.menu, action=self.url, + options=opts) + + @admin_protect + def POST(self, *args, **kwargs): + message = "Nothing was modified." + message_type = "info" + plugins_by_name = {p.name: p for p in self._site[FACILITY]['enabled']} + + if 'order' in kwargs: + order = kwargs['order'].split(',') + if len(order) != 0: + new_names = [] + new_plugins = [] + try: + for v in order: + val = v.strip() + if val not in plugins_by_name: + error = "Invalid plugin name: %s" % val + raise ValueError(error) + new_names.append(val) + new_plugins.append(plugins_by_name[val]) + if len(new_names) < len(plugins_by_name): + for val in plugins_by_name: + if val not in new_names: + new_names.append(val) + new_plugins.append(plugins_by_name[val]) + + po = PluginObject() + po.name = "global" + globalconf = dict() + globalconf['order'] = ','.join(new_names) + po.set_config(globalconf) + po.save_plugin_config(FACILITY) + + # When all is saved update also live config. The + # live config is a list of the actual plugin + # objects. + self._site[FACILITY]['enabled'] = new_plugins + + message = "New configuration saved." + message_type = "success" + + except ValueError, e: + message = str(e) + message_type = "error" + + except Exception, e: # pylint: disable=broad-except + message = "Failed to save data!" + message_type = "error" + + opts = [p.name for p in self._site[FACILITY]['enabled']] + return self._template('admin/info_order.html', + message=message, + message_type=message_type, + title='info plugins order', + name='admin_info_order_form', + menu=self.menu, action=self.url, + options=opts) + + +class InfoPlugins(Page): + def __init__(self, site, parent): + super(InfoPlugins, self).__init__(site) + self._master = parent + self.title = 'Info Plugins' + self.url = '%s/info' % parent.url + self.facility = FACILITY + parent.add_subtree('info', self) + + for plugin in self._site[FACILITY]['available']: + cherrypy.log.error('Admin info plugin: %s' % plugin) + obj = self._site[FACILITY]['available'][plugin] + self.__dict__[plugin] = AdminPluginPage(obj, self._site, self) + + self.order = InfoPluginsOrder(self._site, self) + + def root_with_msg(self, message=None, message_type=None): + info_plugins = self._site[FACILITY] + ordered = [] + for p in info_plugins['enabled']: + ordered.append(p.name) + return self._template('admin/info.html', title=self.title, + message=message, + message_type=message_type, + available=info_plugins['available'], + enabled=ordered, + menu=self._master.menu) + + def root(self, *args, **kwargs): + return self.root_with_msg() + + def enable(self, plugin): + msg = None + plugins = self._site[FACILITY] + if plugin not in plugins['available']: + msg = "Unknown plugin %s" % plugin + return self.root_with_msg(msg, "error") + obj = plugins['available'][plugin] + if obj not in plugins['enabled']: + obj.enable(self._site) + msg = "Plugin %s enabled" % obj.name + return self.root_with_msg(msg, "success") + enable.exposed = True + + def disable(self, plugin): + msg = None + plugins = self._site[FACILITY] + if plugin not in plugins['available']: + msg = "Unknown plugin %s" % plugin + return self.root_with_msg(msg, "error") + obj = plugins['available'][plugin] + if obj in plugins['enabled']: + obj.disable(self._site) + msg = "Plugin %s disabled" % obj.name + return self.root_with_msg(msg, "success") + disable.exposed = True diff --git a/ipsilon/info/common.py b/ipsilon/info/common.py index 6dbaf93..4fbb7ef 100755 --- a/ipsilon/info/common.py +++ b/ipsilon/info/common.py @@ -9,7 +9,7 @@ from ipsilon.util.plugin import PluginLoader, PluginObject from ipsilon.util.plugin import PluginInstaller -class InfoProviderBase(PluginObject): +class InfoProviderBase(PluginObject, Log): def __init__(self): super(InfoProviderBase, self).__init__() @@ -17,17 +17,39 @@ class InfoProviderBase(PluginObject): def get_user_attrs(self, user): raise NotImplementedError + def enable(self, site): + plugins = site[FACILITY] + if self in plugins['enabled']: + return + + # configure self + if self.name in plugins['config']: + self.set_config(plugins['config'][self.name]) + + plugins['enabled'].append(self) + self.debug('Info plugin enabled: %s' % self.name) + + def disable(self, site): + plugins = site[FACILITY] + if self not in plugins['enabled']: + return + + plugins['enabled'].remove(self) + self.debug('Info plugin disabled: %s' % self.name) + FACILITY = 'info_config' class Info(Log): - def __init__(self, *args, **kwargs): + def __init__(self, site): + self._site = site self.providers = [] loader = PluginLoader(Info, FACILITY, 'InfoProvider') - plugins = loader.get_plugin_data() + self._site[FACILITY] = loader.get_plugin_data() + plugins = self._site[FACILITY] available = plugins['available'].keys() self.debug('Available info providers: %s' % str(available)) diff --git a/ipsilon/login/common.py b/ipsilon/login/common.py index 7fb1342..e59085f 100755 --- a/ipsilon/login/common.py +++ b/ipsilon/login/common.py @@ -206,7 +206,7 @@ class Login(Page): def __init__(self, *args, **kwargs): super(Login, self).__init__(*args, **kwargs) self.first_login = None - self.info = Info() + self.info = Info(self._site) loader = PluginLoader(Login, FACILITY, 'LoginManager') self._site[FACILITY] = loader.get_plugin_data() diff --git a/ipsilon/root.py b/ipsilon/root.py index c5fc5ae..0046ddf 100755 --- a/ipsilon/root.py +++ b/ipsilon/root.py @@ -23,6 +23,7 @@ from ipsilon.login.common import Login from ipsilon.login.common import Logout from ipsilon.admin.common import Admin from ipsilon.providers.common import LoadProviders +from ipsilon.admin.info import InfoPlugins from ipsilon.admin.login import LoginPlugins from ipsilon.admin.providers import ProviderPlugins import cherrypy @@ -53,6 +54,7 @@ class Root(Page): # after all plugins are setup we can instantiate the admin pages self.admin = Admin(self._site, 'admin') + InfoPlugins(self._site, self.admin) LoginPlugins(self._site, self.admin) ProviderPlugins(self._site, self.admin) diff --git a/templates/admin/info.html b/templates/admin/info.html new file mode 100644 index 0000000..d51231f --- /dev/null +++ b/templates/admin/info.html @@ -0,0 +1,31 @@ +{% extends "master-admin.html" %} +{% block main %} +{% if user.is_admin %} +

Info plugins

+ {% if message %} +
+

{{ message }}

+
+ {% endif %} + + {% for p in available %} +
+
{{ p }}
+
+ {% if p in enabled %} + Disable + Configure + {% else %} + Enable + {% endif %} +
+
+ {% endfor %} + +

Plugins order

+
{{ ', '.join(enabled) }}
+
+ configure +
+{% endif %} +{% endblock %} diff --git a/templates/admin/info_order.html b/templates/admin/info_order.html new file mode 100644 index 0000000..5d929be --- /dev/null +++ b/templates/admin/info_order.html @@ -0,0 +1,25 @@ +{% extends "master-admin.html" %} +{% block main %} +

{{ title }}

+ {% if message %} +
+

{{ message }}

+
+ {% endif %} +
+
+ +
+ + +
+ Plugins order + + + Back +
+
+{% endblock %} + diff --git a/templates/admin/plugin_config.html b/templates/admin/plugin_config.html index 1f75182..d95bf75 100644 --- a/templates/admin/plugin_config.html +++ b/templates/admin/plugin_config.html @@ -20,7 +20,7 @@ - Back + Back {% endblock %} -- 2.20.1