diff options
Diffstat (limited to 'ipawebui')
-rw-r--r-- | ipawebui/__init__.py | 73 | ||||
-rw-r--r-- | ipawebui/controllers.py | 59 | ||||
-rw-r--r-- | ipawebui/engine.py | 200 | ||||
-rw-r--r-- | ipawebui/widgets.py | 260 |
4 files changed, 0 insertions, 592 deletions
diff --git a/ipawebui/__init__.py b/ipawebui/__init__.py deleted file mode 100644 index 0e892d8a..00000000 --- a/ipawebui/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -# Authors: Jason Gerard DeRose <jderose@redhat.com> -# -# Copyright (C) 2009 Red Hat -# 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; version 2 only -# -# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -""" -IPA web UI. -""" - -# Special wehjit initialization to prevent it from loading the plugins that -# require pygments, which uses ctypes, which makes the httpd SELinux policy -# crazy: -import wehjit -wehjit.builtins._skip_pygments = True -wehjit.init_builtins() - -from ipalib.backend import Executioner -from ipalib.request import destroy_context -from ipaserver.rpcserver import extract_query -from controllers import JSON -from engine import Engine -from widgets import create_widgets - -from assetslib import Assets -from wehjit import Application - - -def join_url(base, url): - if url.startswith('/'): - return url - return base + url - - -class WebUI(Application): - def __init__(self, api): - self.api = api - baseurl = api.env.mount_ipa - assets = Assets( - url=join_url(baseurl, api.env.mount_webui_assets), - dir=api.env.webui_assets_dir, - prod=api.env.webui_prod, - ) - super(WebUI, self).__init__( - url=join_url(baseurl, api.env.mount_webui), - assets=assets, - widgets=create_widgets(), - prod=api.env.webui_prod, - ) - self.api.Backend.session.mount(self, api.env.mount_webui) - - - -def create_wsgi_app(api): - app = WebUI(api) - engine = Engine(api, app) - engine.build() - - app.finalize() - - return app diff --git a/ipawebui/controllers.py b/ipawebui/controllers.py deleted file mode 100644 index 42f1477b..00000000 --- a/ipawebui/controllers.py +++ /dev/null @@ -1,59 +0,0 @@ -# Authors: Jason Gerard DeRose <jderose@redhat.com> -# -# Copyright (C) 2008 Red Hat -# 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; version 2 only -# -# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -""" -Controllers. -""" - -from wehjit import util -from ipalib.compat import json - - -class JSON(object): - def __init__(self, url, api): - self.url = url - self.api = api - - def __repr__(self): - return '%s(url=%r)' % (self.__class__.__name__, self.url) - - def __call__(self, env, start): - util.extract_query(env) - start('200 OK', [('Content-Type', 'text/plain')]) - for key in sorted(env): - yield '%s = %r\n' % (key, env[key]) - - -class Command(object): - def __init__(self, url, cmd, api): - self.url = url - self.cmd = cmd - self.api = api - - def __repr__(self): - return '%s(url=%r)' % (self.__class__.__name__, self.url) - - def __call__(self, env, start): - kw = util.extract_query(env) - ccname = env['KRB5CCNAME'] - self.api.Backend.xmlserver.create_context(ccname) - result = self.api.Backend.xmlserver.execute(self.cmd.name, **kw) - start('200 OK', [('Content-Type', 'text/plain')]) - return [ - json.dumps(result, sort_keys=True, indent=4) - ] diff --git a/ipawebui/engine.py b/ipawebui/engine.py deleted file mode 100644 index dc59b092..00000000 --- a/ipawebui/engine.py +++ /dev/null @@ -1,200 +0,0 @@ -# Authors: Jason Gerard DeRose <jderose@redhat.com> -# -# Copyright (C) 2009 Red Hat -# 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; version 2 only -# -# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -""" -Engine to map ipalib plugins to wehjit widgets. -""" - -from controllers import Command -from ipalib import crud - -class ParamMapper(object): - def __init__(self, api, app): - self._api = api - self._app = app - self.__methods = dict() - for name in dir(self): - if name.startswith('_'): - continue - attr = getattr(self, name) - if not callable(attr): - continue - self.__methods[name] = attr - - def __call__(self, param, cmd): - key = param.__class__.__name__ - if key in self.__methods: - method = self.__methods[key] - else: - method = self.Str - return method(param, cmd) - - def Str(self, param, cmd): - return self._app.new('TextRow', - label=param.label, - name=param.name, - required=param.required, - value=param.default, - ) - - def Password(self, param, cmd): - return self._app.new('PasswordRow', - name=param.name, - required=param.required, - ) - - def Flag(self, param, cmd): - return self._app.new('SelectRow', - name=param.name, - label=param.label, - ) - - -def filter_params(namespace): - for param in namespace(): - if param.exclude and 'webui' in param.exclude: - continue - yield param - - -class Engine(object): - - cruds = frozenset(['add', 'show', 'mod', 'del', 'find']) - - def __init__(self, api, app): - self.api = api - self.app = app - self.param_mapper = ParamMapper(api, app) - self.pages = dict() - self.jsonurl = self.api.Backend.jsonserver.url.rstrip('/') - self.info_pages = [] - - def add_object_menuitems(self, menu, name): - obj = self.api.Object[name] - for cmd in obj.methods(): - p = self.pages[cmd.name] - menu.add( - menu.new('MenuItem', - label=p.title, - href=p.url, - ) - ) - - def build(self): - for obj in self.api.Object(): - if self.cruds.issubset(obj.methods) and obj.primary_key is not None: - self.pages[obj.name] = self.build_cruds_page(obj) - - # Add landing page: - landing = self.app.new('PageApp', id='', title='Welcome to FreeIPA') - - for page in self.pages.values() + [landing]: - page.menu.label = 'FreeIPA' - for name in sorted(self.pages): - p = self.pages[name] - page.menu.new_child('MenuItem', label=p.title, href=p.url) - - - - - # Add in the info pages: - page = self.app.new('PageApp', id='api', title='api') - page.view.add( - self.app.new('API', api=self.api) - ) - self.info_pages.append(page) - - for kind in self.api: - self.build_info_page(kind) - for page in self.info_pages: - for p in self.info_pages: - page.menuset.add( - self.app.new('MenuItem', - href=p.url, - label=p.title, - ) - ) - - def build_cruds_page(self, obj): - page = self.app.new('PageGrid', title=obj.label, id=obj.name) - - # Setup CRUDS widget: - page.cruds.autoload = True - page.cruds.jsonrpc_url = self.api.Backend.jsonserver.url - page.cruds.key = obj.primary_key.name - page.cruds.method_create = obj.methods['add'].name - page.cruds.method_retrieve = obj.methods['show'].name - page.cruds.method_update = obj.methods['mod'].name - page.cruds.method_delete = obj.methods['del'].name - page.cruds.method_search = obj.methods['find'].name - page.cruds.display_cols = tuple( - dict( - name=p.name, - label=p.label, - css_classes=None, - ) - for p in obj.params() - ) - - # Setup the Grid widget: - page.grid.cols = tuple( - dict( - name=p.name, - label=p.label, - css_classes=None, - ) - for p in obj.params() if p.required - ) - - - # Setup the create Dialog: - cmd = obj.methods['add'] - page.create.title = cmd.summary.rstrip('.') - for p in filter_params(cmd.params): - page.create.fieldtable.add(self.param_mapper(p, cmd)) - - # Setup the retrieve Dialog - page.retrieve.title = 'Showing "{value}"' - - # Setup the update Dialog: - page.update.title = 'Updating "{value}"' - cmd = obj.methods['mod'] - for p in filter_params(cmd.options): - page.update.fieldtable.add(self.param_mapper(p, cmd)) - - # Setup the delete Dialog - page.delete.title = 'Delete "{value}"?' - - return page - - def build_info_page(self, kind): - # Add in the Object page: - plugins = tuple(self.api[kind]()) - page = self.app.new('PageApp', id=kind, title=kind) - info = self.app.new('IPAPlugins', kind=kind, plugins=plugins) - quick_jump = self.app.new('QuickJump', - options=tuple((p.name, p.name) for p in plugins) - ) - page.view.add(info) - page.actions.add(quick_jump) - self.info_pages.append(page) - if kind in self.app.widgets: - info.add( - self.app.new(kind) - ) - return page diff --git a/ipawebui/widgets.py b/ipawebui/widgets.py deleted file mode 100644 index 9d6170f1..00000000 --- a/ipawebui/widgets.py +++ /dev/null @@ -1,260 +0,0 @@ -# Authors: Jason Gerard DeRose <jderose@redhat.com> -# -# Copyright (C) 2009 Red Hat -# 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; version 2 only -# -# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -""" -Custom IPA widgets. -""" - -from textwrap import dedent -from wehjit import Collection, base, freeze, builtins -from wehjit.util import Alternator -from wehjit import Static, Dynamic, StaticProp, DynamicProp -from ipaserver.rpcserver import extract_query - - -class IPAPlugins(base.Container): - plugins = Static('plugins', default=tuple()) - kind = Static('kind') - - @DynamicProp - def row(self): - return Alternator(['odd', 'even']) - - xml = """ - <div - xmlns:py="http://genshi.edgewall.org/" - class="${css_classes}" - id="${id}" - > - <p py:content="'%d %s plugins' % (len(plugins), kind)" /> - - <div py:for="p in plugins"> - <h2 id="${p.name}"><a href="#${p.name}" py:content="p.name" /></h2> - - <table class="${row.reset()}"> - - <tr class="${row.next()}"> - <td>module</td> - <td> - <a - title="Link to module documentation" - href="http://freeipa.org/developer-docs/${p.module}-module.html" - py:content="p.module" - /> - </td> - </tr> - - <tr class="${row.next()}"> - <td>base(s)</td> - <td py:content="', '.join(p.bases)" /> - </tr> - - <tr py:if="p.doc" class="${row.next()}"> - <td>docstring</td> - <td><pre py:content="p.doc" /></td> - </tr> - - <tr - py:for="child in children" - py:replace="child.generate(plugin=p, row=row)" - /> - - </table> - </div> - - </div> - """ - - style_global = ( - ('tr.odd', ( - ('background-color', '#ddd'), - )), - ('tr.even', ( - ('background-color', '#eee'), - )), - - ('td', ( - ('vertical-align', 'top'), - ('padding', '0.25em 0.5em'), - )), - ) - - style = ( - ('', ( - ('font-size', '%(font_size_mono)s'), - ('font-family', 'monospace'), - )), - - ('table', ( - ('width', '100%%'), - )), - - ('pre', ( - ('margin', '0'), - )), - - ('th', ( - ('color', '#0a0'), - )), - - ('h2', ( - ('font-family', 'monospace'), - ('font-weight', 'normal'), - ('margin-top', '1.5em'), - ('margin-bottom', '0'), - )), - - ('h2 a', ( - ('text-decoration', 'none'), - ('color', 'inherit'), - )), - - ('h2 a:hover', ( - ('background-color', '#eee'), - )), - - ('h2:target', ( - ('color', '#e02'), - )), - ) - - -class API(base.Widget): - api = Static('api') - - @DynamicProp - def row(self): - return Alternator(['odd', 'even']) - - xml = """ - <div - xmlns:py="http://genshi.edgewall.org/" - class="${css_classes}" - id="${id}" - > - <p py:content="'%d namespaces in API' % len(api)" /> - <table> - <tr py:for="key in api" class="${row.next()}"> - <td> - <a href="${key}" py:content="'api.' + key" /> - </td> - <td py:content="repr(api[key])" /> - </tr> - </table> - </div> - """ - - -class Command(base.Widget): - xml = """ - <table - xmlns:py="http://genshi.edgewall.org/" - py:strip="True" - > - - <tr py:if="plugin.obj" class="${row.next()}"> - <td>Object</td> - <td> - <a href="Object#${plugin.obj.name}" py:content="plugin.obj.fullname" /> - </td> - </tr> - - <tr py:if="plugin.args" class="${row.next()}"> - <th colspan="2" py:content="'args (%d)' % len(plugin.args)" /> - </tr> - <tr py:for="arg in plugin.args()" class="${row.next()}"> - <td py:content="arg.name"/> - <td py:content="repr(arg)" /> - </tr> - - <tr py:if="plugin.options" class="${row.next()}"> - <th colspan="2" py:content="'options (%d)' % len(plugin.options)" /> - </tr> - <tr py:for="option in plugin.options()" class="${row.next()}"> - <td py:content="option.name"/> - <td py:content="repr(option)" /> - </tr> - - <tr py:if="plugin.output" class="${row.next()}"> - <th colspan="2" py:content="'output (%d)' % len(plugin.output)" /> - </tr> - <tr py:for="param in plugin.output()" class="${row.next()}"> - <td py:content="param.name"/> - <td py:content="repr(param)" /> - </tr> - - </table> - """ - - -class Object(base.Widget): - xml = """ - <table - xmlns:py="http://genshi.edgewall.org/" - py:strip="True" - > - <tr py:if="plugin.methods" class="${row.next()}"> - <th colspan="2" py:content="'methods (%d)' % len(plugin.methods)" /> - </tr> - <tr py:for="method in plugin.methods()" class="${row.next()}"> - <td><a href="${'Command#' + method.name}" py:content="method.name"/></td> - <td py:content="method.summary" /> - </tr> - - <tr py:if="plugin.params" class="${row.next()}"> - <th colspan="2" py:content="'params (%d)' % len(plugin.params)" /> - </tr> - <tr py:for="param in plugin.params()" class="${row.next()}"> - <td>${"param.name"}:</td> - <td py:content="repr(param)" /> - </tr> - - </table> - """ - - -class LandingPage(base.Widget): - pages = Static('pages', default=tuple()) - - xml = """ - <div - xmlns:py="http://genshi.edgewall.org/" - class="${css_classes}" - id="${id}" - > - <a - py:for="p in pages" - py:content="p.title" - href="${relurl(p.url)}" - /> - </div> - """ - - -def create_widgets(): - widgets = Collection('freeIPA') - widgets.register_builtins() - - widgets.register(API) - widgets.register(IPAPlugins) - widgets.register(Command) - widgets.register(Object) - widgets.register(LandingPage) - - freeze(widgets) - return widgets |