Add infrastructure to configure server
authorSimo Sorce <simo@redhat.com>
Fri, 24 Jan 2014 19:20:42 +0000 (14:20 -0500)
committerSimo Sorce <simo@redhat.com>
Fri, 24 Jan 2014 22:32:21 +0000 (17:32 -0500)
Signed-off-by: Simo Sorce <simo@redhat.com>
ipsilon/admin/__init__.py [new file with mode: 0644]
ipsilon/admin/common.py [new file with mode: 0755]
ipsilon/root.py
setup.py
templates/admin/index.html [new file with mode: 0644]
templates/admin/login_plugin.html [new file with mode: 0644]
templates/index.html

diff --git a/ipsilon/admin/__init__.py b/ipsilon/admin/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ipsilon/admin/common.py b/ipsilon/admin/common.py
new file mode 100755 (executable)
index 0000000..7620d3f
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2014  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/>.
+
+from ipsilon.util.data import Store
+from ipsilon.util.page import Page
+from ipsilon.util.user import UserSession
+import cherrypy
+from ipsilon.login.common import FACILITY as LOGIN_FACILITY
+
+
+def admin_protect(fn):
+
+    def check(*args, **kwargs):
+        if UserSession().get_user().is_admin:
+            return fn(*args, **kwargs)
+
+        raise cherrypy.HTTPError(403)
+
+    return check
+
+
+class LoginPluginPage(Page):
+
+    def __init__(self, obj, site, baseurl):
+        super(LoginPluginPage, self).__init__(site)
+        self._obj = obj
+        self.url = '%s/%s' % (baseurl, obj.name)
+
+        # Get the defaults
+        self.plugin_config = obj.get_config_desc()
+        if not self.plugin_config:
+            self.plugin_config = []
+
+        # Now overlay the actual config
+        for option in self.plugin_config:
+            self.plugin_config[option][2] = obj.get_config_value(option)
+
+    @admin_protect
+    def GET(self, *args, **kwargs):
+        return self._template('admin/login_plugin.html',
+                              title='%s plugin' % self._obj.name,
+                              name='admin_login_%s_form' % self._obj.name,
+                              action=self.url,
+                              options=self.plugin_config)
+
+    @admin_protect
+    def POST(self, *args, **kwargs):
+
+        message = "Nothing was modified."
+        new_values = dict()
+
+        for key, value in kwargs.iteritems():
+            if key in self.plugin_config:
+                if value != self.plugin_config[key][2]:
+                    cherrypy.log.error("Storing [%s]: %s = %s" %
+                                       (self._obj.name, key, value))
+                    new_values[key] = value
+
+        if len(new_values) != 0:
+            # First we try to save in the database
+            try:
+                store = Store()
+                store.save_plugin_config(LOGIN_FACILITY,
+                                         self._obj.name, new_values)
+                message = "New configuration saved."
+            except Exception:  # pylint: disable=broad-except
+                message = "Failed to save data!"
+
+            # And only if it succeeds we change the live object
+            for name, value in new_values.items():
+                self._obj.set_config_value(name, value)
+                self.plugin_config[name][2] = value
+
+        return self._template('admin/login_plugin.html',
+                              message=message,
+                              title='%s plugin' % self._obj.name,
+                              name='admin_login_%s_form' % self._obj.name,
+                              action=self.url,
+                              options=self.plugin_config)
+
+    def root(self, *args, **kwargs):
+        cherrypy.log.error("method: %s" % cherrypy.request.method)
+        op = getattr(self, cherrypy.request.method, self.GET)
+        if callable(op):
+            return op(*args, **kwargs)
+
+
+class LoginPlugins(Page):
+    def __init__(self, site, baseurl):
+        super(LoginPlugins, self).__init__(site)
+        self.url = '%s/login' % baseurl
+
+        for plugin in self._site[LOGIN_FACILITY]['available']:
+            cherrypy.log.error('Admin login plugin: %s' % plugin)
+            obj = self._site[LOGIN_FACILITY]['available'][plugin]
+            self.__dict__[plugin] = LoginPluginPage(obj, self._site, self.url)
+
+
+class Admin(Page):
+
+    def __init__(self, *args, **kwargs):
+        super(Admin, self).__init__(*args, **kwargs)
+        self.url = '%s/admin' % self.basepath
+        self.login = LoginPlugins(self._site, self.url)
+
+    def root(self, *args, **kwargs):
+        login_plugins = self._site[LOGIN_FACILITY]
+        return self._template('admin/index.html', title='Administration',
+                              available=login_plugins['available'],
+                              enabled=login_plugins['enabled'])
index 30f6b43..279cbd4 100755 (executable)
@@ -20,6 +20,7 @@
 from ipsilon.util.page import Page
 from ipsilon.login.common import Login
 from ipsilon.login.common import Logout
+from ipsilon.admin.common import Admin
 
 sites = dict()
 
@@ -37,5 +38,8 @@ class Root(Page):
         self.login = Login(self._site)
         self.logout = Logout(self._site)
 
+        # after all plugins are setup we can instantiate the admin pages
+        self.admin = Admin(self._site)
+
     def root(self):
         return self._template('index.html', title='Root')
index 30a6239..80e03b5 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -23,7 +23,7 @@ setup(
     name = 'ipsilon',
     version = '0.1',
     license = 'GPLv3+',
-    packages = ['ipsilon', 'ipsilon.login', 'ipsilon.util'],
+    packages = ['ipsilon', 'ipsilon.admin', 'ipsilon.login', 'ipsilon.util'],
     data_files = [('share/man/man7', ["man/ipsilon.7"]),
                   ('doc', ['COPYING']),
                   ('examples', ['examples/ipsilon.conf'])]
diff --git a/templates/admin/index.html b/templates/admin/index.html
new file mode 100644 (file)
index 0000000..5af8497
--- /dev/null
@@ -0,0 +1,41 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8"></meta>
+    <title>{{ title }}</title>
+    <link href="{{ basepath }}/ui/ipsilon.css" type="text/css" rel="stylesheet"></link>
+    <link href="{{ basepath }}/ui/favicon.ico" type="image/ico" rel="icon"></link>
+</head>
+<body>
+    <div id="container">
+        <div id="logo">
+            <p><a href="{{ basepath }}">Ipsilon</a></p>
+        </div>
+        <div id="logout">
+            <p><a href="{{ basepath }}/logout">Log Out</a></p>
+        </div>
+        <div id="options">
+            {% if user.is_admin %}
+                <p>Login plugins:</p>
+                <ul>
+                {% for p in available %}
+                    <li> {{ p }} -
+                    {% if p in enabled %}
+                        <a href="{{ basepath }}/admin/login/{{ p }}/disable">Disable</a> -
+                        <a href="{{ basepath }}/admin/login/{{ p }}">Configure</a>
+                    {% else %}
+                        <a href="{{ basepath }}/admin/login/{{ p }}/enable">Enable</a>
+                    {% endif %}
+                    </li>
+                {% endfor %}
+                </ul>
+                <p>Plugins order: [list here and form button to change?]</p>
+            {% endif %}
+        </div>
+        <div id="home">
+            <p><a href="{{ basepath }}/">Home</a></p>
+        </div>
+    </div>
+</body>
+</html>
+
diff --git a/templates/admin/login_plugin.html b/templates/admin/login_plugin.html
new file mode 100644 (file)
index 0000000..43adac6
--- /dev/null
@@ -0,0 +1,42 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8"></meta>
+    <title>{{ title }}</title>
+    <link href="{{ basepath }}/ui/ipsilon.css" type="text/css" rel="stylesheet"></link>
+    <link href="{{ basepath }}/ui/favicon.ico" type="image/ico" rel="icon"></link>
+</head>
+<body>
+    <div id="container">
+        <div id="logo">
+            <p><a href="{{ basepath }}">Ipsilon</a></p>
+        </div>
+        <div id="logout">
+            <p><a href="{{ basepath }}/logout">Log Out</a></p>
+        </div>
+        <div id="message">
+            <p>{{ message }}</p>
+        </div>
+        <div id="options">
+            <form id="{{ name }}" action="{{ action }}" method="post" enctype="application/x-www-form-urlencoded">
+            <ul>
+            {% for o in options %}
+                <li>{{ o }}:
+                    <p>{{ options[o][0] }}</p>
+                    <input type="text" name="{{ o }}" value="{{ options[o][2] }}">
+                </li>
+            {% endfor %}
+            </ul>
+            <input id="submit" name="submit" type="submit" value="Submit">
+            </form>
+        </div>
+        <div id="home">
+            <p>
+                <a href="{{ basepath }}/admin">Admin</a> -
+                <a href="{{ basepath }}/">Home</a>
+            </p>
+        </div>
+    </div>
+</body>
+</html>
+
index c983af2..1e21948 100644 (file)
@@ -13,7 +13,7 @@
         </div>
         <div id="admin">
             {% if user.is_admin %}
-                <a href="admin">admin</a>
+                <a href="{{ basepath }}/admin">admin</a>
             {% endif %}
         </div>
         <div id="welcome">