Add "Extending FreeIPA" developer guide

"Extending FreeIPA" is a developer guide of FreeIPA core framework.
Please make sure to improve the guide every time parts of the core framework
are affected by your changes. This document ideally should correspond to
the current state of the framework.

The Guide is written using Emacs Org Mode but can be edited with any
plain text editing tool. Emacs is only required to convert it to
distribution formats like HTML and TXT.

See guide/Makefile for building the guide and README for details of
the build environment.
This commit is contained in:
Alexander Bokovoy 2011-11-22 15:39:23 +02:00
parent 17cc52a154
commit d09389ab6f
6 changed files with 1360 additions and 0 deletions

36
doc/guide/Makefile Normal file
View File

@ -0,0 +1,36 @@
FILE=guide.org
XML=$(addsuffix .xml, $(basename $(FILE)))
PDF=$(addsuffix .pdf, $(basename $(FILE)))
TXT=$(addsuffix .txt, $(basename $(FILE)))
HTML=$(addsuffix .html, $(basename $(FILE)))
FO=$(addsuffix .fo, $(basename $(FILE)))
all: $(PDF) $(TXT) $(HTML)
@echo Finished: $? are created
plain: $(FILE)
@echo -n "Building HTML, Docbook, and plain text ..."
@emacs -batch -q --no-site-file -eval "(require 'org)" \
--visit $< -f org-export-as-html \
--visit $< -f org-export-as-docbook \
--visit $< -f org-export-as-ascii 2>/dev/null
@echo "done, see $(HTML), $(XML), $(TXT)"
$(TXT): plain
$(HTML): plain
$(XML): plain
$(FO): $(XML)
@xmlto --skip-validation fo $< 2>/dev/null
$(PDF): $(FO)
@echo -n "Building PDF ... "
@fop -fo $< -pdf $@ -l en -a 2>/dev/null
@echo "done, see $(PDF)"
.PHONY: clean
clean:
@rm -f *.html *.txt *.xml *.fo *.pdf *~

36
doc/guide/README Normal file
View File

@ -0,0 +1,36 @@
Extending FreeIPA
-----------------
"Extending FreeIPA" is a developer guide to understand how FreeIPA core
framework is built and how to extend it.
The Guide is written using Emacs Org Mode, see http://orgmode.org/org.html
for extensive manual of supported markup features.
You don't need to use Emacs to edit it, the markup is a plain text.
Building the guide
------------------
There is Makefile which can be used to convert the Guide from
Emacs Org Mode format to different targets.
Prerequisites:
==============
On Fedora system following packages are required to generate The Guide:
docbook-style-xsl
fop
emacs
xmlto
HTML, Docbook, and plain text
---
As Org Mode is part of Emacs since version 22, building HTML, TXT, and
Docbook targets requires Emacs v22 and above (tested with v23.3 in Fedora).
PDF
---
Building PDF is done first generating Docbook source, converting it to FO format,
and then running 'fop' processor.

1060
doc/guide/guide.org Normal file

File diff suppressed because it is too large Load Diff

62
doc/guide/netgroup.js Normal file
View File

@ -0,0 +1,62 @@
IPA.netgroup = {};
IPA.netgroup.entity = function(spec) {
var that = IPA.entity(spec);
that.init = function(params) {
params.builder.search_facet({
columns: [
'cn',
'description'
]
}).
details_facet({
sections: [
{
name: 'identity',
fields: [
'cn',
{
factory: IPA.textarea_widget,
name: 'description'
},
'nisdomainname'
]
}
]
}).
association_facet({
name: 'memberhost_host',
facet_group: 'member'
}).
association_facet({
name: 'memberhost_hostgroup',
facet_group: 'member'
}).
association_facet({
name: 'memberuser_user',
facet_group: 'member'
}).
association_facet({
name: 'memberuser_group',
facet_group: 'member'
}).
association_facet({
name: 'memberof_netgroup',
associator: IPA.serial_associator
}).
standard_association_facets().
adder_dialog({
fields: [
'cn',
{
factory: IPA.textarea_widget,
name: 'description'
}
]
});
};
return that;
};
IPA.register('netgroup', IPA.netgroup.entity);

140
doc/guide/role.py Normal file
View File

@ -0,0 +1,140 @@
from ipalib.plugins.baseldap import *
from ipalib import api, Str, _, ngettext
from ipalib import Command
from ipalib.plugins import privilege
class role(LDAPObject):
"""
Role object.
"""
container_dn = api.env.container_rolegroup
object_name = _('role')
object_name_plural = _('roles')
object_class = ['groupofnames', 'nestedgroup']
default_attributes = ['cn', 'description', 'member', 'memberof',
'memberindirect', 'memberofindirect',
]
attribute_members = {
'member': ['user', 'group', 'host', 'hostgroup'],
'memberof': ['privilege'],
}
reverse_members = {
'member': ['privilege'],
}
rdnattr='cn'
label = _('Roles')
label_singular = _('Role')
takes_params = (
Str('cn',
cli_name='name',
label=_('Role name'),
primary_key=True,
),
Str('description',
cli_name='desc',
label=_('Description'),
doc=_('A description of this role-group'),
),
)
api.register(role)
class role_add(LDAPCreate):
__doc__ = _('Add a new role.')
msg_summary = _('Added role "%(value)s"')
api.register(role_add)
class role_del(LDAPDelete):
__doc__ = _('Delete a role.')
msg_summary = _('Deleted role "%(value)s"')
api.register(role_del)
class role_mod(LDAPUpdate):
__doc__ = _('Modify a role.')
msg_summary = _('Modified role "%(value)s"')
api.register(role_mod)
class role_find(LDAPSearch):
__doc__ = _('Search for roles.')
msg_summary = ngettext(
'%(count)d role matched', '%(count)d roles matched', 0
)
api.register(role_find)
class role_show(LDAPRetrieve):
__doc__ = _('Display information about a role.')
api.register(role_show)
class role_add_member(LDAPAddMember):
__doc__ = _('Add members to a role.')
api.register(role_add_member)
class role_remove_member(LDAPRemoveMember):
__doc__ = _('Remove members from a role.')
api.register(role_remove_member)
class role_add_privilege(LDAPAddReverseMember):
__doc__ = _('Add privileges to a role.')
show_command = 'role_show'
member_command = 'privilege_add_member'
reverse_attr = 'privilege'
member_attr = 'role'
has_output = (
output.Entry('result'),
output.Output('failed',
type=dict,
doc=_('Members that could not be added'),
),
output.Output('completed',
type=int,
doc=_('Number of privileges added'),
),
)
api.register(role_add_privilege)
class role_remove_privilege(LDAPRemoveReverseMember):
__doc__ = _('Remove privileges from a role.')
show_command = 'role_show'
member_command = 'privilege_remove_member'
reverse_attr = 'privilege'
member_attr = 'role'
has_output = (
output.Entry('result'),
output.Output('failed',
type=dict,
doc=_('Members that could not be added'),
),
output.Output('completed',
type=int,
doc=_('Number of privileges removed'),
),
)
api.register(role_remove_privilege)

26
doc/guide/wsgi.py Normal file
View File

@ -0,0 +1,26 @@
from ipalib import api
from ipalib.config import Env
from ipalib.constants import DEFAULT_CONFIG
# Determine what debug level is configured. We can only do this
# by reading in the configuration file(s). The server always reads
# default.conf and will also read in `context'.conf.
env = Env()
env._bootstrap(context='server', log=None)
env._finalize_core(**dict(DEFAULT_CONFIG))
# Initialize the API with the proper debug level
api.bootstrap(context='server', debug=env.debug, log=None) (ref:wsgi-app-bootstrap)
try:
api.finalize() (ref:wsgi-app-finalize)
except StandardError, e:
api.log.error('Failed to start IPA: %s' % e)
else:
api.log.info('*** PROCESS START ***')
# This is the WSGI callable:
def application(environ, start_response): (ref:wsgi-app-start)
if not environ['wsgi.multithread']:
return api.Backend.session(environ, start_response)
else:
api.log.error("IPA does not work with the threaded MPM, use the pre-fork MPM") (ref:wsgi-app-end)