mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Addiing initial turbogears web gui.
Contains simple user add, list, and view pages.
This commit is contained in:
parent
a3e786e22e
commit
728e44833c
4
ipa-server/ipa-gui/README.txt
Normal file
4
ipa-server/ipa-gui/README.txt
Normal file
@@ -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.
|
||||||
66
ipa-server/ipa-gui/dev.cfg
Normal file
66
ipa-server/ipa-gui/dev.cfg
Normal file
@@ -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
|
||||||
15
ipa-server/ipa-gui/ipa_gui.egg-info/PKG-INFO
Normal file
15
ipa-server/ipa-gui/ipa_gui.egg-info/PKG-INFO
Normal file
@@ -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
|
||||||
21
ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt
Normal file
21
ipa-server/ipa-gui/ipa_gui.egg-info/SOURCES.txt
Normal file
@@ -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
|
||||||
1
ipa-server/ipa-gui/ipa_gui.egg-info/dependency_links.txt
Normal file
1
ipa-server/ipa-gui/ipa_gui.egg-info/dependency_links.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
ipa-server/ipa-gui/ipa_gui.egg-info/not-zip-safe
Normal file
1
ipa-server/ipa-gui/ipa_gui.egg-info/not-zip-safe
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
2
ipa-server/ipa-gui/ipa_gui.egg-info/paster_plugins.txt
Normal file
2
ipa-server/ipa-gui/ipa_gui.egg-info/paster_plugins.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
TurboGears
|
||||||
|
PasteScript
|
||||||
1
ipa-server/ipa-gui/ipa_gui.egg-info/requires.txt
Normal file
1
ipa-server/ipa-gui/ipa_gui.egg-info/requires.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
TurboGears >= 1.0.2.2
|
||||||
2
ipa-server/ipa-gui/ipa_gui.egg-info/sqlobject.txt
Normal file
2
ipa-server/ipa-gui/ipa_gui.egg-info/sqlobject.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
db_module=ipagui.model
|
||||||
|
history_dir=$base/ipagui/sqlobject-history
|
||||||
1
ipa-server/ipa-gui/ipa_gui.egg-info/top_level.txt
Normal file
1
ipa-server/ipa-gui/ipa_gui.egg-info/top_level.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ipagui
|
||||||
51
ipa-server/ipa-gui/ipagui/config/app.cfg
Normal file
51
ipa-server/ipa-gui/ipagui/config/app.cfg
Normal file
@@ -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"
|
||||||
29
ipa-server/ipa-gui/ipagui/config/log.cfg
Normal file
29
ipa-server/ipa-gui/ipagui/config/log.cfg
Normal file
@@ -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,)'
|
||||||
168
ipa-server/ipa-gui/ipagui/controllers.py
Normal file
168
ipa-server/ipa-gui/ipagui/controllers.py
Normal file
@@ -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@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()
|
||||||
67
ipa-server/ipa-gui/ipagui/forms/user.py
Normal file
67
ipa-server/ipa-gui/ipagui/forms/user.py
Normal file
@@ -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)
|
||||||
10
ipa-server/ipa-gui/ipagui/json.py
Normal file
10
ipa-server/ipa-gui/ipagui/json.py
Normal file
@@ -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
|
||||||
|
|
||||||
9
ipa-server/ipa-gui/ipagui/model.py
Normal file
9
ipa-server/ipa-gui/ipagui/model.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from turbogears.database import PackageHub
|
||||||
|
from sqlobject import *
|
||||||
|
|
||||||
|
hub = PackageHub('ipagui')
|
||||||
|
__connection__ = hub
|
||||||
|
|
||||||
|
# class YourDataClass(SQLObject):
|
||||||
|
# pass
|
||||||
|
|
||||||
14
ipa-server/ipa-gui/ipagui/release.py
Normal file
14
ipa-server/ipa-gui/ipagui/release.py
Normal file
@@ -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@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"
|
||||||
146
ipa-server/ipa-gui/ipagui/static/css/style.css
Normal file
146
ipa-server/ipa-gui/ipagui/static/css/style.css
Normal file
@@ -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;
|
||||||
|
}
|
||||||
18
ipa-server/ipa-gui/ipagui/templates/groupindex.kid
Normal file
18
ipa-server/ipa-gui/ipagui/templates/groupindex.kid
Normal file
@@ -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>
|
||||||
22
ipa-server/ipa-gui/ipagui/templates/grouplayout.kid
Normal file
22
ipa-server/ipa-gui/ipagui/templates/grouplayout.kid
Normal file
@@ -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>
|
||||||
112
ipa-server/ipa-gui/ipagui/templates/login.kid
Normal file
112
ipa-server/ipa-gui/ipagui/templates/login.kid
Normal file
@@ -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>
|
||||||
48
ipa-server/ipa-gui/ipagui/templates/master.kid
Normal file
48
ipa-server/ipa-gui/ipagui/templates/master.kid
Normal file
@@ -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>
|
||||||
18
ipa-server/ipa-gui/ipagui/templates/resindex.kid
Normal file
18
ipa-server/ipa-gui/ipagui/templates/resindex.kid
Normal file
@@ -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>
|
||||||
22
ipa-server/ipa-gui/ipagui/templates/reslayout.kid
Normal file
22
ipa-server/ipa-gui/ipagui/templates/reslayout.kid
Normal file
@@ -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>
|
||||||
13
ipa-server/ipa-gui/ipagui/templates/useredit.kid
Normal file
13
ipa-server/ipa-gui/ipagui/templates/useredit.kid
Normal file
@@ -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>
|
||||||
125
ipa-server/ipa-gui/ipagui/templates/userform.kid
Normal file
125
ipa-server/ipa-gui/ipagui/templates/userform.kid
Normal file
@@ -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>
|
||||||
22
ipa-server/ipa-gui/ipagui/templates/userlayout.kid
Normal file
22
ipa-server/ipa-gui/ipagui/templates/userlayout.kid
Normal file
@@ -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>
|
||||||
26
ipa-server/ipa-gui/ipagui/templates/userlist.kid
Normal file
26
ipa-server/ipa-gui/ipagui/templates/userlist.kid
Normal file
@@ -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>
|
||||||
13
ipa-server/ipa-gui/ipagui/templates/usernew.kid
Normal file
13
ipa-server/ipa-gui/ipagui/templates/usernew.kid
Normal file
@@ -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>
|
||||||
50
ipa-server/ipa-gui/ipagui/templates/usershow.kid
Normal file
50
ipa-server/ipa-gui/ipagui/templates/usershow.kid
Normal file
@@ -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>
|
||||||
18
ipa-server/ipa-gui/ipagui/templates/welcome.kid
Normal file
18
ipa-server/ipa-gui/ipagui/templates/welcome.kid
Normal file
@@ -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>
|
||||||
32
ipa-server/ipa-gui/ipagui/tests/test_controllers.py
Normal file
32
ipa-server/ipa-gui/ipagui/tests/test_controllers.py
Normal file
@@ -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
|
||||||
|
|
||||||
22
ipa-server/ipa-gui/ipagui/tests/test_model.py
Normal file
22
ipa-server/ipa-gui/ipagui/tests/test_model.py
Normal file
@@ -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@python.not",
|
||||||
|
# display_name = "Mr Creosote",
|
||||||
|
# password = "Wafer-thin Mint")
|
||||||
|
# assert obj.display_name == "Mr Creosote"
|
||||||
|
|
||||||
84
ipa-server/ipa-gui/sample-prod.cfg
Normal file
84
ipa-server/ipa-gui/sample-prod.cfg
Normal file
@@ -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
|
||||||
62
ipa-server/ipa-gui/setup.py
Normal file
62
ipa-server/ipa-gui/setup.py
Normal file
@@ -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',
|
||||||
|
)
|
||||||
|
|
||||||
25
ipa-server/ipa-gui/start-ipagui.py
Normal file
25
ipa-server/ipa-gui/start-ipagui.py
Normal file
@@ -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())
|
||||||
4
ipa-server/ipa-gui/test.cfg
Normal file
4
ipa-server/ipa-gui/test.cfg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# You can place test-specific configuration options here (like test db uri, etc)
|
||||||
|
|
||||||
|
sqlobject.dburi = "sqlite:///:memory:"
|
||||||
|
|
||||||
Reference in New Issue
Block a user