[Freeipa-devel] [PATCH] initial IPA turbogears gui checkin

Kevin McCarthy kmccarth at redhat.com
Fri Aug 10 15:55:21 UTC 2007


Attached is an initial check-in for the turbogears front-end.  It has a
very simple add/show/list user functionality and a lot of stubbing
everywhere else.

The patch also contains some of the turbogears template files generated
by tg-admin when generating the framework.  I don't know enough about
these files to know what's necessary and what's not just yet so thought
it would be better to check them all in.

I've put the files under ipa-server/ipa-gui, but can move an resubmit if
you prefer another place.

-Kevin

-------------- next part --------------
# HG changeset patch
# User kmccarth at redhat.com
# Date 1186919598 25200
# Node ID 59663a581e56401f8f3f7e802f064058d9052324
# Parent  c7a2e210de44785bded93953d69c46e7b80ab047
Addiing initial turbogears web gui.
Contains simple user add, list, and view pages.

diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/README.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/README.txt	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,4 @@
+ipa-gui
+
+This is a TurboGears (http://www.turbogears.org) project. It can be
+started by running the start-ipagui.py script.
\ No newline at end of file
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/dev.cfg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/dev.cfg	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,66 @@
+[global]
+# This is where all of your settings go for your development environment
+# Settings that are the same for both development and production
+# (such as template engine, encodings, etc.) all go in 
+# ipagui/config/app.cfg
+
+# DATABASE
+
+# pick the form for your database
+# sqlobject.dburi="postgres://username@hostname/databasename"
+# sqlobject.dburi="mysql://username:password@hostname:port/databasename"
+# sqlobject.dburi="sqlite:///file_name_and_path"
+
+# If you have sqlite, here's a simple default to get you started
+# in development
+sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"
+
+
+# if you are using a database or table type without transactions
+# (MySQL default, for example), you should turn off transactions
+# by prepending notrans_ on the uri
+# sqlobject.dburi="notrans_mysql://username:password@hostname:port/databasename"
+
+# for Windows users, sqlite URIs look like:
+# sqlobject.dburi="sqlite:///drive_letter:/path/to/file"
+
+# SERVER
+
+# Some server parameters that you may want to tweak
+# server.socket_port=8080
+
+# Enable the debug output at the end on pages.
+# log_debug_info_filter.on = False
+
+server.environment="development"
+autoreload.package="ipagui"
+
+# Auto-Reload after code modification
+# autoreload.on = True
+
+# Set to True if you'd like to abort execution if a controller gets an
+# unexpected parameter. False by default
+tg.strict_parameters = True
+
+# LOGGING
+# Logging configuration generally follows the style of the standard
+# Python logging module configuration. Note that when specifying
+# log format messages, you need to use *() for formatting variables.
+# Deployment independent log configuration is in ipagui/config/log.cfg
+[logging]
+
+[[loggers]]
+[[[ipagui]]]
+level='DEBUG'
+qualname='ipagui'
+handlers=['debug_out']
+
+[[[allinfo]]]
+level='INFO'
+handlers=['debug_out']
+
+[[[access]]]
+level='INFO'
+qualname='turbogears.access'
+handlers=['access_out']
+propagate=0
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipa_gui.egg-info/PKG-INFO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipa_gui.egg-info/PKG-INFO	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,15 @@
+Metadata-Version: 1.0
+Name: ipa-gui
+Version: 1.0
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: UNKNOWN
+Author-email: UNKNOWN
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
+Classifier: Development Status :: 3 - Alpha
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Framework :: TurboGears
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,21 @@
+README.txt
+setup.py
+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/not-zip-safe
+ipa_gui.egg-info/paster_plugins.txt
+ipa_gui.egg-info/requires.txt
+ipa_gui.egg-info/sqlobject.txt
+ipa_gui.egg-info/top_level.txt
+ipagui/__init__.py
+ipagui/controllers.py
+ipagui/json.py
+ipagui/model.py
+ipagui/release.py
+ipagui/config/__init__.py
+ipagui/templates/__init__.py
+ipagui/tests/__init__.py
+ipagui/tests/test_controllers.py
+ipagui/tests/test_model.py
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipa_gui.egg-info/dependency_links.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipa_gui.egg-info/dependency_links.txt	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,1 @@
+
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipa_gui.egg-info/not-zip-safe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipa_gui.egg-info/not-zip-safe	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,1 @@
+
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipa_gui.egg-info/paster_plugins.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipa_gui.egg-info/paster_plugins.txt	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,2 @@
+TurboGears
+PasteScript
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipa_gui.egg-info/requires.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipa_gui.egg-info/requires.txt	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,1 @@
+TurboGears >= 1.0.2.2
\ No newline at end of file
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipa_gui.egg-info/sqlobject.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipa_gui.egg-info/sqlobject.txt	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,2 @@
+db_module=ipagui.model
+history_dir=$base/ipagui/sqlobject-history
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipa_gui.egg-info/top_level.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipa_gui.egg-info/top_level.txt	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,1 @@
+ipagui
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/config/app.cfg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/config/app.cfg	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,51 @@
+[global]
+# The settings in this file should not vary depending on the deployment
+# environment. dev.cfg and prod.cfg are the locations for
+# the different deployment settings. Settings in this file will
+# be overridden by settings in those other files.
+
+# The commented out values below are the defaults
+
+# VIEW
+
+# which view (template engine) to use if one is not specified in the
+# template name
+# tg.defaultview = "kid"
+
+# The following kid settings determine the settings used by the kid serializer.
+
+# One of (html|html-strict|xhtml|xhtml-strict|xml|json)
+# kid.outputformat="html"
+
+# kid.encoding="utf-8"
+
+# The sitetemplate is used for overall styling of a site that
+# includes multiple TurboGears applications
+# tg.sitetemplate="<packagename.templates.templatename>"
+
+# Allow every exposed function to be called as json,
+# tg.allow_json = False
+
+# List of Widgets to include on every page.
+# for exemple ['turbogears.mochikit']
+# tg.include_widgets = []
+
+# Set to True if the scheduler should be started
+# tg.scheduler = False
+
+# Set session or cookie
+# session_filter.on = True
+
+
+# compress the data sends to the web browser
+# [/] 
+# gzip_filter.on = True
+# gzip_filter.mime_types = ["application/x-javascript", "text/javascript", "text/html", "text/css", "text/plain"]
+
+[/static]
+static_filter.on = True
+static_filter.dir = "%(top_level_dir)s/static"
+
+[/favicon.ico]
+static_filter.on = True
+static_filter.file = "%(top_level_dir)s/static/images/favicon.ico"
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/config/log.cfg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/config/log.cfg	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,29 @@
+# LOGGING
+# Logging is often deployment specific, but some handlers and
+# formatters can be defined here.
+
+[logging]
+[[formatters]]
+[[[message_only]]]
+format='*(message)s'
+
+[[[full_content]]]
+format='*(asctime)s *(name)s *(levelname)s *(message)s'
+
+[[handlers]]
+[[[debug_out]]]
+class='StreamHandler'
+level='DEBUG'
+args='(sys.stdout,)'
+formatter='full_content'
+
+[[[access_out]]]
+class='StreamHandler'
+level='INFO'
+args='(sys.stdout,)'
+formatter='message_only'
+
+[[[error_out]]]
+class='StreamHandler'
+level='ERROR'
+args='(sys.stdout,)'
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/controllers.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/controllers.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,168 @@
+import cherrypy
+import turbogears
+from turbogears import controllers, expose, flash
+from turbogears import validators, validate
+from turbogears import widgets, paginate
+from turbogears import error_handler
+# from model import *
+# import logging
+# log = logging.getLogger("ipagui.controllers")
+# import ipa.rpcclient
+import ipa.config
+import ipa.ipaclient
+import ipa.user
+import xmlrpclib
+import forms.user
+
+ipa.config.init_config()
+user_form = forms.user.UserFormWidget()
+
+client = ipa.ipaclient.IPAClient(True)
+client.set_principal("test at FREEIPA.ORG")
+
+def restrict_post():
+    if cherrypy.request.method != "POST":
+        turbogears.flash("This method only accepts posts")
+        raise turbogears.redirect("/")
+
+def user_to_hash(user):
+    return {
+        'uid'       : user.getValue('uid'),
+        'givenName' : user.getValue('givenName'),
+        'sn'        : user.getValue('sn'),
+        'mail'      : user.getValue('mail'),
+        'telephoneNumber': user.getValue('telephoneNumber'),
+        'uidNumber': user.getValue('uidNumber'),
+        'gidNumber': user.getValue('gidNumber'),
+            }
+
+class Root(controllers.RootController):
+
+    @expose(template="ipagui.templates.welcome")
+    def index(self):
+        return dict()
+
+
+    ########
+    # User #
+    ########
+
+    @expose("ipagui.templates.usernew")
+    def usernew(self, tg_errors=None):
+        """Displays the new user form"""
+        if tg_errors:
+            turbogears.flash("There was a problem with the form!")
+
+        return dict(form=user_form)
+
+    @expose()
+    def usercreate(self, **kw):
+        """Creates a new user"""
+        restrict_post()
+        if kw.get('submit') == 'Cancel':
+            turbogears.flash("Add user cancelled")
+            raise turbogears.redirect('/userlist')
+
+        tg_errors, kw = self.uservalidate(**kw)
+        if tg_errors:
+            return dict(form=user_form, tg_template='ipagui.templates.usernew')
+
+        try:
+            # rv = ipa.rpcclient.add_user(kw)
+            newuser = ipa.user.User(None)
+            newuser.setValue('uid', kw['uid'])
+            newuser.setValue('givenName', kw['givenName'])
+            newuser.setValue('sn', kw['sn'])
+            newuser.setValue('mail', kw['mail'])
+            newuser.setValue('telephoneNumber', kw['telephoneNumber'])
+            newuser2 = {
+                'uid'       : kw['uid'],
+                'givenName' : kw['givenName'],
+                'sn'        : kw['sn'],
+                'mail'      : kw['mail'],
+                'telephoneNumber': kw['telephoneNumber']
+                    }
+            rv = client.add_user(newuser2)
+            turbogears.flash("%s added!" % kw['uid'])
+            raise turbogears.redirect('/usershow', uid=kw['uid'])
+        except xmlrpclib.Fault, f:
+            turbogears.flash("User add failed: " + str(f.faultString))
+            return dict(form=user_form, tg_template='ipagui.templates.usernew')
+
+
+    @expose("ipagui.templates.useredit")
+    def useredit(self, uid, tg_errors=None):
+        """Displays the edit user form"""
+        if tg_errors:
+            turbogears.flash("There was a problem with the form!")
+
+        # user = ipa.rpcclient.get_user(uid)
+        user = client.get_user(uid)
+        return dict(form=user_form, user=user_to_hash(user))
+
+    @expose()
+    def userupdate(self, **kw):
+        """Updates an existing user"""
+        restrict_post()
+        if kw.get('submit') == 'Cancel':
+            turbogears.flash("Edit user cancelled")
+            raise turbogears.redirect('/usershow', uid=kw.get('uid'))
+
+        tg_errors, kw = self.uservalidate(**kw)
+        if tg_errors:
+            return dict(form=user_form, user={}, tg_template='ipagui.templates.useredit')
+
+        try:
+            # rv = ipa.rpcclient.add_user(kw)
+            turbogears.flash("%s updated!" % kw['uid'])
+            raise turbogears.redirect('/usershow', uid=kw['uid'])
+        except xmlrpclib.Fault, f:
+            turbogears.flash("User add failed: " + str(f.faultString))
+            return dict(form=user_form, user={}, tg_template='ipagui.templates.useredit')
+
+
+    @expose("ipagui.templates.userlist")
+    @paginate('users', limit=3, allow_limit_override=True)
+    def userlist(self):
+        """Retrieve a list of all users and display them in one huge list"""
+        # users = ipa.rpcclient.get_all_users()
+        users = client.get_all_users()
+        return dict(users=users)
+
+
+    @expose("ipagui.templates.usershow")
+    def usershow(self, uid):
+        """Retrieve a single user for display"""
+        try:
+            # user = ipa.rpcclient.get_user(uid)
+            user = client.get_user(uid)
+            return dict(user=user_to_hash(user))
+        except xmlrpclib.Fault, f:
+            turbogears.flash("User show failed: " + str(f.faultString))
+            raise turbogears.redirect("/")
+
+    @validate(form=user_form)
+    def uservalidate(self, tg_errors=None, **kw):
+        return tg_errors, kw
+
+    @expose()
+    def userindex(self):
+        raise turbogears.redirect("/userlist")
+
+
+    #########
+    # Group #
+    #########
+
+    @expose("ipagui.templates.groupindex")
+    def groupindex(self, tg_errors=None):
+        return dict()
+
+
+    ############
+    # Resource #
+    ############
+
+    @expose("ipagui.templates.resindex")
+    def resindex(self, tg_errors=None):
+        return dict()
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/forms/user.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/forms/user.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,67 @@
+import turbogears
+from turbogears import validators, widgets
+
+class UserFields():
+    uid = widgets.TextField(name="uid", label="Login:")
+    userPassword = widgets.TextField(name="userPassword", label="Password:")
+    uidNumber = widgets.TextField(name="uidNumber", label="UID:")
+    gidNumber = widgets.TextField(name="gidNumber", label="GID:")
+    givenName = widgets.TextField(name="givenName", label="First name:")
+    sn = widgets.TextField(name="sn", label="Last name:")
+    mail = widgets.TextField(name="mail", label="E-mail address:")
+    telephoneNumber = widgets.TextField(name="telephoneNumber", label="Phone:")
+
+    uid.validator = validators.PlainText(not_empty=True)
+    userPassword.validator = validators.String(not_empty=True)
+    givenName.validator = validators.String(not_empty=True)
+    sn.validator = validators.String(not_empty=True)
+    mail.validator = validators.Email(not_empty=True)
+    #  validators.PhoneNumber may be a bit too picky, requiring an area code
+    telephoneNumber.validator = validators.PlainText(not_empty=True)
+
+
+class UserFormWidget(widgets.Form):
+    params = ['user']
+#     fields = [UserFields.uid, UserFields.userPassword, UserFields.givenName,
+#               UserFields.sn, UserFields.mail]
+    fields = [UserFields.uid, UserFields.givenName,
+              UserFields.uidNumber, UserFields.gidNumber,
+               UserFields.sn, UserFields.mail]
+
+    def __init__(self, *args, **kw):
+        super(UserFormWidget,self).__init__(*args, **kw)
+        (self.template_c, self.template) = widgets.meta.load_kid_template("ipagui.templates.userform")
+        self.user = UserFields
+
+    def update_params(self, params):
+        super(UserFormWidget,self).update_params(params)
+        params['has_foo'] = self.has_foo
+
+    def has_foo(self):
+        return False
+
+# TODO - add dynamic field retrieval:
+#      myfields=[]
+#      schema = ipa.rpcclient.get_add_schema ()
+# 
+#      # FIXME: What if schema is None or an error is thrown?
+# 
+#      for s in schema:
+#          required=False
+# 
+#          if (s['type'] == "text"):
+#              field = widgets.TextField(name=s['name'],label=s['label'])
+#          elif (s['type'] == "password"):
+#              field = widgets.PasswordField(name=s['name'],label=s['label'])
+# 
+#          if (s['required'] == "true"):
+#              required=True
+# 
+#          if (s['validator'] == "text"):
+#              field.validator=validators.PlainText(not_empty=required)
+#          elif (s['validator'] == "email"):
+#              field.validator=validators.Email(not_empty=required)
+#          elif (s['validator'] == "string"):
+#              field.validator=validators.String(not_empty=required)
+# 
+#          myfields.append(field)
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/json.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/json.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,10 @@
+# A JSON-based API(view) for your app.
+# Most rules would look like:
+# @jsonify.when("isinstance(obj, YourClass)")
+# def jsonify_yourclass(obj):
+#     return [obj.val1, obj.val2]
+# @jsonify can convert your objects to following types:
+# lists, dicts, numbers and strings
+
+from turbojson.jsonify import jsonify
+
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/model.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/model.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,9 @@
+from turbogears.database import PackageHub
+from sqlobject import *
+
+hub = PackageHub('ipagui')
+__connection__ = hub
+
+# class YourDataClass(SQLObject):
+#     pass
+
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/release.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/release.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,14 @@
+# Release information about ipa-gui
+
+version = "1.0"
+
+# description = "Your plan to rule the world"
+# long_description = "More description about your plan"
+# author = "Your Name Here"
+# email = "YourEmail at YourDomain"
+# copyright = "Vintage 2006 - a good year indeed"
+
+# if it's open source, you might want to specify these
+# url = "http://yourcool.site/"
+# download_url = "http://yourcool.site/download"
+# license = "MIT"
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/static/css/style.css
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/static/css/style.css	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,146 @@
+/*
+ * Quick mash-up of CSS for the TG quick start page.
+ */
+
+html, body {
+  color: #000;
+  background:#fff;
+  margin: 0;
+  padding: 0;
+}
+
+body {
+  min-width: 750px;
+}
+
+#page {
+  background:#ccc;   /* should be same as #sidebar */
+  margin:0 auto;
+  width:100%;
+}
+
+
+#header {
+  background:#fff;
+}
+
+#header h1 {
+  padding:5px;
+  margin:0;
+}
+
+
+#nav {
+  background:#cc0000;
+  color:#fff;
+  padding:5px;
+}
+
+#nav ul {
+  margin:0;
+  padding:0;
+  list-style:none;
+}
+
+#nav li {
+  display:inline;
+}
+
+#nav a:visited {
+  color:#fff;
+}
+#nav a:link {
+  color:#fff;
+}
+
+
+#main_content {
+  background:#fff;
+  float:right;
+  width:85%;
+  border-left: 1px solid #000;
+  padding-left: 15px;
+  padding-bottom: 15px;
+/*  color: black;
+  font-size: 127%;
+  background-color: white;
+  margin: 0 auto 0 auto;
+  padding: 10px;
+  float: left; */
+}
+
+
+#sidebar {
+  background:#ccc;  /* should be same as #page */
+  float:left;
+  width:10%;
+  /* border: 1px solid #aaa;
+  background-color: #eee;
+  margin: 0.5em;
+  padding: 1em;
+  float: left;
+  font-size: 88%; */
+}
+
+#sidebar h2 {
+  margin-top: 0;
+}
+
+#sidebar ul {
+  margin-left: 1.5em;
+  padding-left: 0;
+}
+
+
+#footer {
+  background:#fff;
+  clear:both;
+  border-top: 1px solid #000;
+  /* color: #999;
+  background-color: white;
+  padding: 10px;
+  font-size: 80%;
+  text-align: center;
+  margin: 0 auto 1em auto; */
+}
+
+
+.formsection {
+  color: #888888;
+  width: 90%;
+  font-weight: bold;
+  border-bottom: 1px solid;
+  margin: 20px 0px 20px 0px;
+}
+
+.formtable {
+  width: 90%;
+}
+
+.formtable th {
+  width: 15%;
+  text-align: right;
+}
+
+#status_block {
+  margin: 0 auto 0.5em auto;
+  padding: 15px 10px 15px 55px;
+  background: #cec URL('../images/ok.png') left center no-repeat;
+  border: 1px solid #9c9;
+  width: 450px;
+  font-size: 120%;
+  font-weight: bolder;
+}
+
+.notice {
+  margin: 0.5em auto 0.5em auto;
+  padding: 15px 10px 15px 55px;
+  width: 450px;
+  background: #eef URL('../images/info.png') left center no-repeat;
+  border: 1px solid #cce;
+}
+
+.fielderror {
+    color: red;
+    font-weight: bold;
+}
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/static/images/favicon.ico
Binary file ipa-server/ipa-gui/ipagui/static/images/favicon.ico has changed
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/static/images/header_inner.png
Binary file ipa-server/ipa-gui/ipagui/static/images/header_inner.png has changed
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/static/images/info.png
Binary file ipa-server/ipa-gui/ipagui/static/images/info.png has changed
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/static/images/ok.png
Binary file ipa-server/ipa-gui/ipagui/static/images/ok.png has changed
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/static/images/tg_under_the_hood.png
Binary file ipa-server/ipa-gui/ipagui/static/images/tg_under_the_hood.png has changed
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/static/images/under_the_hood_blue.png
Binary file ipa-server/ipa-gui/ipagui/static/images/under_the_hood_blue.png has changed
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/groupindex.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/groupindex.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'grouplayout.kid'">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
+<title>Group Listing</title>
+</head>
+<body>
+       Groups go here.
+       <br />
+       <br />
+       <br />
+       <br />
+       <br />
+       <br />
+       <br />
+</body>
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/grouplayout.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/grouplayout.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'master.kid'">
+<head>
+</head>
+
+<body py:match="item.tag=='{http://www.w3.org/1999/xhtml}body'" py:attrs="item.items()">
+      <div id="main_content">
+        <div id="status_block" class="flash" py:if="value_of('tg_flash', None)" py:content="tg_flash"></div>
+
+        <div py:replace="[item.text]+item[:]"></div>
+      </div>
+
+      <div id="sidebar">
+          <h2>Tools</h2>
+          <a href="${tg.url('/groupindex')}">Add Group</a><br/>
+          <a href="${tg.url('/groupindex')}">Find Group</a><br/>
+          <a href="${tg.url('/groupindex')}">List Groups</a><br/>
+      </div>
+</body>
+
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/login.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/login.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,112 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:py="http://purl.org/kid/ns#">
+
+<head>
+    <meta content="text/html; charset=UTF-8"
+        http-equiv="content-type" py:replace="''"/>
+    <title>Login</title>
+    <style type="text/css">
+        #loginBox
+        {
+            width: 30%;
+            margin: auto;
+            margin-top: 10%;
+            padding-left: 10%;
+            padding-right: 10%;
+            padding-top: 5%;
+            padding-bottom: 5%;
+            font-family: verdana;
+            font-size: 10px;
+            background-color: #eee;
+            border: 2px solid #ccc;
+        }
+
+        #loginBox h1
+        {
+            font-size: 42px;
+            font-family: "Trebuchet MS";
+            margin: 0;
+            color: #ddd;
+        }
+
+        #loginBox p
+        {
+            position: relative;
+            top: -1.5em;
+            padding-left: 4em;
+            font-size: 12px;
+            margin: 0;
+            color: #666;
+        }
+
+        #loginBox table
+        {
+            table-layout: fixed;
+            border-spacing: 0;
+            width: 100%;
+        }
+
+        #loginBox td.label
+        {
+            width: 33%;
+            text-align: right;
+        }
+
+        #loginBox td.field
+        {
+            width: 66%;
+        }
+
+        #loginBox td.field input
+        {
+            width: 100%;
+        }
+
+        #loginBox td.buttons
+        {
+            text-align: right;
+        }
+
+    </style>
+</head>
+
+<body>
+    <div id="loginBox">
+        <h1>Login</h1>
+        <p>${message}</p>
+        <form action="${previous_url}" method="POST">
+            <table>
+                <tr>
+                    <td class="label">
+                        <label for="user_name">User Name:</label>
+                    </td>
+                    <td class="field">
+                        <input type="text" id="user_name" name="user_name"/>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="label">
+                        <label for="password">Password:</label>
+                    </td>
+                    <td class="field">
+                        <input type="password" id="password" name="password"/>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="2" class="buttons">
+                        <input type="submit" name="login" value="Login"/>
+                    </td>
+                </tr>
+            </table>
+
+            <input py:if="forward_url" type="hidden" name="forward_url"
+                value="${forward_url}"/>
+                
+            <input py:for="name,value in original_parameters.items()"
+                type="hidden" name="${name}" value="${value}"/>
+        </form>
+    </div>
+</body>
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/master.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/master.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,48 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<?python import sitetemplate ?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#" py:extends="sitetemplate">
+
+<head py:match="item.tag=='{http://www.w3.org/1999/xhtml}head'" py:attrs="item.items()">
+    <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
+    <title py:replace="''">Your title goes here</title>
+    <meta py:replace="item[:]"/>
+    <style type="text/css" media="screen">
+    @import "${tg.url('/static/css/style.css')}";
+    </style>
+</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="page">
+      <div id="header">
+        <h1>Free IPA</h1>
+      </div>
+
+      <div id="nav">
+        <ul>
+          <li><a href="${tg.url('/userindex')}">Users</a></li>
+          <li><a href="${tg.url('/groupindex')}">Groups</a></li>
+          <li><a href="${tg.url('/resindex')}">Resources</a></li>
+        </ul>
+      </div>
+
+      <div py:replace="[item.text]+item[:]"></div>
+
+
+      <div id="footer">
+        This is the footer
+      </div>
+    </div>
+
+</body>
+
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/resindex.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/resindex.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'reslayout.kid'">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
+<title>Resource Listing</title>
+</head>
+<body>
+       Resources go here.
+       <br />
+       <br />
+       <br />
+       <br />
+       <br />
+       <br />
+       <br />
+</body>
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/reslayout.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/reslayout.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'master.kid'">
+<head>
+</head>
+
+<body py:match="item.tag=='{http://www.w3.org/1999/xhtml}body'" py:attrs="item.items()">
+      <div id="main_content">
+        <div id="status_block" class="flash" py:if="value_of('tg_flash', None)" py:content="tg_flash"></div>
+
+        <div py:replace="[item.text]+item[:]"></div>
+      </div>
+
+      <div id="sidebar">
+          <h2>Tools</h2>
+          <a href="${tg.url('/resindex')}">Add Resource</a><br/>
+          <a href="${tg.url('/resindex')}">Find Resource</a><br/>
+          <a href="${tg.url('/resindex')}">List Resources</a><br/>
+      </div>
+</body>
+
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/useredit.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/useredit.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'userlayout.kid'">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
+<title>Edit a Person</title>
+</head>
+<body>
+    <h2>Edit User</h2>
+
+     ${form.display(action="userupdate", value=user)}
+</body>
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/userform.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/userform.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,125 @@
+<div xmlns:py="http://purl.org/kid/ns#"
+  class="simpleroster">
+  <form action="${action}" name="${name}" method="${method}" class="tableform">
+
+    <div class="formsection">Account Details</div>
+    <table class="formtable" cellpadding="2" cellspacing="0" border="0">
+      <tr>
+        <th>
+          <label class="fieldlabel" for="${user.uid.field_id}"
+            py:content="user.uid.label" />
+        </th>
+        <td>
+          <span py:replace="user.uid.display(value_for(user.uid))" />
+          <span py:if="tg.errors.get('uid')" class="fielderror"
+              py:content="tg.errors.get('uid')" />
+        </td>
+      </tr>
+
+<!--      <tr>
+        <th>
+          <label class="fieldlabel" for="${user.userPassword.field_id}"
+            py:content="user.userPassword.label" />
+        </th>
+        <td>
+          <span py:replace="user.userPassword.display(value_for(user.userPassword))" />
+          <span py:if="tg.errors.get('userPassword')" class="fielderror"
+              py:content="tg.errors.get('userPassword')" />
+        </td>
+      </tr> -->
+
+      <tr>
+        <th>
+          <label class="fieldlabel" for="${user.uidNumber.field_id}"
+            py:content="user.uidNumber.label" />
+        </th>
+        <td>
+          <span py:replace="user.uidNumber.display(value_for(user.uidNumber))" />
+          <span py:if="tg.errors.get('uidNumber')" class="fielderror"
+              py:content="tg.errors.get('uidNumber')" />
+        </td>
+      </tr>
+
+      <tr>
+        <th>
+          <label class="fieldlabel" for="${user.gidNumber.field_id}"
+            py:content="user.gidNumber.label" />
+        </th>
+        <td>
+          <span py:replace="user.gidNumber.display(value_for(user.gidNumber))" />
+          <span py:if="tg.errors.get('gidNumber')" class="fielderror"
+              py:content="tg.errors.get('gidNumber')" />
+        </td>
+      </tr>
+    </table>
+
+    <div class="formsection">Identity Details</div>
+    <table class="formtable" cellpadding="2" cellspacing="0" border="0">
+      <tr>
+        <th>
+          <label class="fieldlabel" for="${user.givenName.field_id}"
+            py:content="user.givenName.label" />
+        </th>
+        <td>
+          <span py:replace="user.givenName.display(value_for(user.givenName))" />
+          <span py:if="tg.errors.get('givenName')" class="fielderror"
+              py:content="tg.errors.get('givenName')" />
+
+        </td>
+      </tr>
+
+      <tr>
+        <th>
+          <label class="fieldlabel" for="${user.sn.field_id}"
+            py:content="user.sn.label" />
+        </th>
+        <td>
+          <span py:replace="user.sn.display(value_for(user.sn))" />
+          <span py:if="tg.errors.get('sn')" class="fielderror"
+              py:content="tg.errors.get('sn')" />
+        </td>
+      </tr>
+    </table>
+
+    <div class="formsection">Contact Details</div>
+    <table class="formtable" cellpadding="2" cellspacing="0" border="0">
+      <tr>
+        <th>
+          <label class="fieldlabel" for="${user.mail.field_id}"
+            py:content="user.mail.label" />
+        </th>
+        <td>
+          <span py:replace="user.mail.display(value_for(user.mail))" />
+          <span py:if="tg.errors.get('mail')" class="fielderror"
+              py:content="tg.errors.get('mail')" />
+        </td>
+      </tr>
+      <tr>
+        <th>
+          <label class="fieldlabel" for="${user.telephoneNumber.field_id}"
+            py:content="user.telephoneNumber.label" />
+        </th>
+        <td>
+          <span py:replace="user.telephoneNumber.display(value_for(user.telephoneNumber))" />
+          <span py:if="tg.errors.get('telephoneNumber')" class="fielderror"
+              py:content="tg.errors.get('telephoneNumber')" />
+        </td>
+      </tr>
+    </table>
+
+    <table class="formtable" cellpadding="2" cellspacing="0" border="0">
+      <tr>
+        <th>
+          <br />
+          <input type="submit" class="submitbutton" name="submit" value="Submit"/>
+        </th>
+        <td>
+          <br />
+          <input type="submit" class="submitbutton" name="submit" value="Cancel" />
+        </td>
+        <td></td>
+      </tr>
+    </table>
+
+  </form>
+</div>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/userlayout.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/userlayout.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'master.kid'">
+<head>
+</head>
+
+<body py:match="item.tag=='{http://www.w3.org/1999/xhtml}body'" py:attrs="item.items()">
+      <div id="main_content">
+        <div id="status_block" class="flash" py:if="value_of('tg_flash', None)" py:content="tg_flash"></div>
+
+        <div py:replace="[item.text]+item[:]"></div>
+      </div>
+
+      <div id="sidebar">
+          <h2>Tools</h2>
+          <a href="${tg.url('/usernew')}">Add Person</a><br/>
+          <a href="${tg.url('/userindex')}">Find People</a><br/>
+          <a href="${tg.url('/userlist')}">List People</a><br/>
+      </div>
+</body>
+
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/userlist.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/userlist.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'userlayout.kid'">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
+<title>User Listing</title>
+</head>
+<body>
+      <fieldset>
+        <legend>People List</legend>
+        <div>
+          Page: 
+          <span py:for="page in tg.paginate.pages">
+              <a py:if="page != tg.paginate.current_page"
+                  href="${tg.paginate.get_href(page)}">${page}</a>
+              <b py:if="page == tg.paginate.current_page">${page}</b>
+          </span>
+          <p/>
+          <span py:for="user in users">
+             <a href="${tg.url('/usershow',uid=user.uid)}">${user.cn}</a>
+            <br/>
+          </span>
+        </div>
+       </fieldset>
+</body>
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/usernew.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/usernew.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'userlayout.kid'">
+<head>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
+    <title>Add a Person</title>
+</head>
+<body>
+    <h2>Add New User</h2>
+
+    ${form.display(action="usercreate")}
+</body>
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/usershow.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/usershow.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,50 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'userlayout.kid'">
+<head>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
+    <title>View a Person</title>
+</head>
+<body>
+    <h2>View User</h2>
+
+    <div class="formsection">Account Details</div>
+    <table class="formtable" cellpadding="2" cellspacing="0" border="0">
+        <tr>
+          <th>User ID:</th>
+          <td>${user.get("uid")}</td>
+        </tr>
+        <tr>
+          <th>UID:</th>
+          <td>${user.get("uidNumber")}</td>
+        </tr>
+        <tr>
+          <th>GID:</th>
+          <td>${user.get("gidNumber")}</td>
+        </tr>
+    </table>
+
+    <div class="formsection">Identity Details</div>
+    <table class="formtable" cellpadding="2" cellspacing="0" border="0">
+        <tr>
+          <th>Full Name:</th>
+          <td>${user.get("givenName")} ${user.get("sn")}</td>
+        </tr>
+    </table>
+
+    <div class="formsection">Contact Details</div>
+    <table class="formtable" cellpadding="2" cellspacing="0" border="0">
+        <tr>
+          <th>Email:</th>
+          <td>${user.get("mail")}</td>
+        </tr>
+        <tr>
+          <th>Telephone:</th>
+          <td>${user.get("telephoneNumber")}</td>
+        </tr>
+    </table>
+
+    <a href="${tg.url('/useredit', uid=user.get('uid'))}">edit</a>
+
+</body>
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/templates/welcome.kid
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/templates/welcome.kid	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
+    py:extends="'master.kid'">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
+<title>Welcome</title>
+</head>
+<body>
+    <div id="sidebar">
+        <h2>Tools</h2>
+    </div>
+    <div id="main_content">
+        <div id="status_block" class="flash" py:if="value_of('tg_flash', None)" py:content="tg_flash"></div>
+        <h1>Welcome to Free IPA</h1>
+    </div>
+
+</body>
+</html>
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/tests/test_controllers.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/tests/test_controllers.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,32 @@
+import unittest
+import turbogears
+from turbogears import testutil
+from ipagui.controllers import Root
+import cherrypy
+
+cherrypy.root = Root()
+
+class TestPages(unittest.TestCase):
+
+    def setUp(self):
+        turbogears.startup.startTurboGears()
+
+    def tearDown(self):
+        """Tests for apps using identity need to stop CP/TG after each test to
+        stop the VisitManager thread. 
+        See http://trac.turbogears.org/turbogears/ticket/1217 for details.
+        """
+        turbogears.startup.stopTurboGears()
+
+    def test_method(self):
+        "the index method should return a string called now"
+        import types
+        result = testutil.call(cherrypy.root.index)
+        assert type(result["now"]) == types.StringType
+
+    def test_indextitle(self):
+        "The indexpage should have the right title"
+        testutil.createRequest("/")
+        response = cherrypy.response.body[0].lower() 
+        assert "<title>welcome to turbogears</title>" in response
+
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/ipagui/tests/test_model.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/ipagui/tests/test_model.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,22 @@
+# If your project uses a database, you can set up database tests
+# similar to what you see below. Be sure to set the db_uri to
+# an appropriate uri for your testing database. sqlite is a good
+# choice for testing, because you can use an in-memory database
+# which is very fast.
+
+from turbogears import testutil, database
+# from ipagui.model import YourDataClass, User
+
+# database.set_db_uri("sqlite:///:memory:")
+
+# class TestUser(testutil.DBTest):
+#     def get_model(self):
+#         return User
+#     def test_creation(self):
+#         "Object creation should set the name"
+#         obj = User(user_name = "creosote",
+#                       email_address = "spam at python.not",
+#                       display_name = "Mr Creosote",
+#                       password = "Wafer-thin Mint")
+#         assert obj.display_name == "Mr Creosote"
+
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/sample-prod.cfg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/sample-prod.cfg	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,84 @@
+[global]
+# This is where all of your settings go for your production environment.
+# You'll copy this file over to your production server and provide it
+# as a command-line option to your start script.
+# Settings that are the same for both development and production
+# (such as template engine, encodings, etc.) all go in 
+# ipagui/config/app.cfg
+
+# DATABASE
+
+# pick the form for your database
+# sqlobject.dburi="postgres://username@hostname/databasename"
+# sqlobject.dburi="mysql://username:password@hostname:port/databasename"
+# sqlobject.dburi="sqlite:///file_name_and_path"
+
+# If you have sqlite, here's a simple default to get you started
+# in development
+sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"
+
+
+# if you are using a database or table type without transactions
+# (MySQL default, for example), you should turn off transactions
+# by prepending notrans_ on the uri
+# sqlobject.dburi="notrans_mysql://username:password@hostname:port/databasename"
+
+# for Windows users, sqlite URIs look like:
+# sqlobject.dburi="sqlite:///drive_letter:/path/to/file"
+
+
+# SERVER
+
+server.environment="production"
+
+# Sets the number of threads the server uses
+# server.thread_pool = 1
+
+# if this is part of a larger site, you can set the path
+# to the TurboGears instance here
+# server.webpath=""
+
+# Set to True if you are deploying your App behind a proxy
+# e.g. Apache using mod_proxy
+# base_url_filter.on = False
+
+# Set to True if your proxy adds the x_forwarded_host header
+# base_url_filter.use_x_forwarded_host = True
+
+# If your proxy does not add the x_forwarded_host header, set
+# the following to the *public* host url.
+# (Note: This will be overridden by the use_x_forwarded_host option
+# if it is set to True and the proxy adds the header correctly.
+# base_url_filter.base_url = "http://www.example.com"
+
+# Set to True if you'd like to abort execution if a controller gets an
+# unexpected parameter. False by default
+# tg.strict_parameters = False
+
+# LOGGING
+# Logging configuration generally follows the style of the standard
+# Python logging module configuration. Note that when specifying
+# log format messages, you need to use *() for formatting variables.
+# Deployment independent log configuration is in ipagui/config/log.cfg
+[logging]
+
+[[handlers]]
+
+[[[access_out]]]
+# set the filename as the first argument below
+args="('server.log',)"
+class='FileHandler'
+level='INFO'
+formatter='message_only'
+
+[[loggers]]
+[[[ipagui]]]
+level='ERROR'
+qualname='ipagui'
+handlers=['error_out']
+
+[[[access]]]
+level='INFO'
+qualname='turbogears.access'
+handlers=['access_out']
+propagate=0
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/setup.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/setup.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,62 @@
+from setuptools import setup, find_packages
+from turbogears.finddata import find_package_data
+
+import os
+execfile(os.path.join("ipagui", "release.py"))
+
+setup(
+    name="ipa-gui",
+    version=version,
+    
+    # uncomment the following lines if you fill them out in release.py
+    #description=description,
+    #author=author,
+    #author_email=email,
+    #url=url,
+    #download_url=download_url,
+    #license=license,
+    
+    install_requires = [
+        "TurboGears >= 1.0.2.2",
+    ],
+    scripts = ["start-ipagui.py"],
+    zip_safe=False,
+    packages=find_packages(),
+    package_data = find_package_data(where='ipagui',
+                                     package='ipagui'),
+    keywords = [
+        # Use keywords if you'll be adding your package to the
+        # Python Cheeseshop
+        
+        # if this has widgets, uncomment the next line
+        # 'turbogears.widgets',
+        
+        # if this has a tg-admin command, uncomment the next line
+        # 'turbogears.command',
+        
+        # if this has identity providers, uncomment the next line
+        # 'turbogears.identity.provider',
+    
+        # If this is a template plugin, uncomment the next line
+        # 'python.templating.engines',
+        
+        # If this is a full application, uncomment the next line
+        # 'turbogears.app',
+    ],
+    classifiers = [
+        'Development Status :: 3 - Alpha',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Topic :: Software Development :: Libraries :: Python Modules',
+        'Framework :: TurboGears',
+        # if this is an application that you'll distribute through
+        # the Cheeseshop, uncomment the next line
+        # 'Framework :: TurboGears :: Applications',
+        
+        # if this is a package that includes widgets that you'll distribute
+        # through the Cheeseshop, uncomment the next line
+        # 'Framework :: TurboGears :: Widgets',
+    ],
+    test_suite = 'nose.collector',
+    )
+    
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/start-ipagui.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/start-ipagui.py	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+import pkg_resources
+pkg_resources.require("TurboGears")
+
+from turbogears import update_config, start_server
+import cherrypy
+cherrypy.lowercase_api = True
+from os.path import *
+import sys
+
+# first look on the command line for a desired config file,
+# if it's not on the command line, then
+# look for setup.py in this directory. If it's not there, this script is
+# probably installed
+if len(sys.argv) > 1:
+    update_config(configfile=sys.argv[1], 
+        modulename="ipagui.config")
+elif exists(join(dirname(__file__), "setup.py")):
+    update_config(configfile="dev.cfg",modulename="ipagui.config")
+else:
+    update_config(configfile="prod.cfg",modulename="ipagui.config")
+
+from ipagui.controllers import Root
+
+start_server(Root())
diff -r c7a2e210de44 -r 59663a581e56 ipa-server/ipa-gui/test.cfg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipa-server/ipa-gui/test.cfg	Sun Aug 12 04:53:18 2007 -0700
@@ -0,0 +1,4 @@
+# You can place test-specific configuration options here (like test db uri, etc)
+
+sqlobject.dburi = "sqlite:///:memory:"
+
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 2228 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20070810/61d47388/attachment.bin>


More information about the Freeipa-devel mailing list