Plugin for cone.app providing a user and group management UI.
- Users and Groups CRUD
- Principal membership of users and groups
- Roles support
- Local Manager Support
- User and group form configuration
While installation lxml gets compiled, the required dev headers must be
installed on the system.
On debian based systems install:
$ apt-get install -y libxml2-dev libxslt1-devFor testing and demo purposes, an example UGM configuration is contained in the
cfg folder of the source package.
It contains the configuration file ugm.xml, containing the general UGM
configuration and localmanager.xml, containing the configuration about
local users and groups management. These two files can be edited TTW via the
settings UI.
The ugm.ini file contains the application configuration:
[app:ugm]
...
cone.plugins =
cone.ugm
ugm.backend = file
ugm.config = %(here)s/ugm.xml
ugm.localmanager_config = %(here)s/localmanager.xml
ugm.users_file = %(here)s/../parts/ugm/users
ugm.groups_file = %(here)s/../parts/ugm/groups
ugm.roles_file = %(here)s/../parts/ugm/roles
ugm.datadir = %(here)s/../parts/ugm/data
...In this example the file backend is configured as UGM backend. For
configuring SQL or LDAP based backends, see documentation at cone.sql
respective cone.ldap.
Start the application:
cone.ugm$ ./bin/pserver cfg/ugm.iniand browse http://localhost:8081/. Default admin user password is
admin.
For customizing the plugin, make an integration package and include it in your setup.
cone.ugm internally uses 3 roles in order to permit user actions.
editor is permitted to manage membership, admin additionally is
permitted to add, edit and delete users and groups, and manager is a
superuser. If UGM is the only plugin used, you can reduce the available roles
to this three:
cone.app.security.DEFAULT_ROLES = [
('editor', 'Editor'),
('admin', 'Admin'),
('manager', 'Manager')
]The basic principal form customization happens in the ugm XML configuration
file. Each field to render must have an entry in users_form_attrmap
respective groups_form_attrmap:
<users_form_attrmap>
<elem>
<key>my_field</key>
<value>My Field</value>
</elem>
</users_form_attrmap>By default, a non required text field gets rendered for each custom entry in the XML configuration.
To make a custom field required, the easiest way is to use
default_form_field_factory and register it with user_field
respective group_field:
from cone.ugm.browser.principal import default_form_field_factory
from cone.ugm.browser.principal import user_field
from functools import partial
my_field_factory = user_field('my_field')(
partial(default_form_field_factory, required=True)
)It's possible to register custom principal field factories for dedicated
UGM backends. This example is taken from cone.ldap and registers a
user field factory for cn attribute in ldap backend:
ldap_cn_field_factory = user_field('cn', backend='ldap')(
partial(default_form_field_factory, required=True)
)The most flexible way for principal form field customization is to provide a callback function and call the yafowil factory directly:
from yafowil.base import factory
@user_field('age')
def age_field_factory(form, label, value):
return factory(
'field:label:error:number',
value=value,
props={
'label': label,
'datatype': int
})Note. The value of the custom field gets written to principal attributes as extracted from the widget. Make sure to define the expected datatype in the widget properties or define a suitable custom extractor.
XXX
You can react to creation, modification and deletion of users and groups by binding to the given event classes.
These events are fired when the user manipulations are done in the UGM management forms.
necessary imports:
from zope.event import classhandler
from cone.ugm import eventsfor users:
@classhandler.handler(events.UserCreatedEvent)
def on_user_created(event):
print(f"user {event.principal} with id {event.principal.name} created")
@classhandler.handler(events.UserModifiedEvent)
def on_user_modified(event):
print(f"user {event.principal} with id {event.principal.name} modified")
@classhandler.handler(events.UserDeletedEvent)
def on_user_deleted(event):
print(f"user {event.principal} with id {event.principal.name} deleted")and for groups:
@classhandler.handler(events.GroupCreatedEvent)
def on_group_created(event):
print(f"group {event.principal} with id {event.principal.name} created")
@classhandler.handler(events.GroupModifiedEvent)
def on_group_modified(event):
print(f"group {event.principal} with id {event.principal.name} modified")
@classhandler.handler(events.GroupDeletedEvent)
def on_group_deleted(event):
print(f"group {event.principal} with id {event.principal.name} deleted")For testing and development, cone.ugm contains a buildout configuration.
Download or checkout package and run:
cone.ugm$ ./bootstrap.sh python3Install test requirements:
npm --save-dev install \
qunit \
karma \
karma-qunit \
karma-coverage \
karma-chrome-launcher \
karma-viewport \
karma-module-resolver-preprocessor
Install jquery from git as jquery 4 is not released yet but required to run tests as modules and import from jquery sources works:
npm --save-dev install https://github.com/jquery/jquery#main
Install deployment requirements:
npm --save-dev install \
rollup \
rollup-plugin-cleanup \
rollup-plugin-terser
Install treibstoff and cone.app from local folder or from git repo.:
npm install https://github.com/conestack/treibstoff#master npm install https://github.com/conestack/cone.app#master
Start karma server (immediately run tests):
./karma.sh
To view coverage report, open:
karma/coverage/[browser name]/index.html
Create JS bundle with rollup:
./rollup.sh
- Robert Niederreiter (Author)
- Florian Friesdorf
- Jens Klein