Files
modoboa/doc/plugin_api.rst
T

319 lines
9.3 KiB
ReStructuredText

Extending Modoboa
*****************
Introduction
============
Modoboa offers a plugin API to expand its capabilities. The current
implementation provides the following possibilities:
* Expand navigation by adding entry points to your plugin inside the GUI
* Access and modify administrative objects (domains, mailboxes, etc.)
* Register callback actions for specific events
Plugins are nothing more than Django applications with an extra file
called ``main.py``. This file contains a complete description of the
plugin:
* Admin and user parameters
* Registered events
* Custom menu entries
The communication between both applications is provided by
events. Modoboa offers some kind of hooks to let plugin add custom
actions.
The following subsections describe plugin architecture and explain
how you can create your own plugin.
Adding a custom plugin
======================
All Modoboa plugins must be located inside the ``extensions``
directory. To create a new plugin, execute the following steps:
* Run ``python manage.py startapp`` to get some basefiles for your plugin,
* Move the resulting directory inside the ``extensions`` one,
* Create a file called ``main.py`` inside your plugin's directory.
The last file you created (ie. ``main.py``) must follow a specific
structure in order to be interpreted by Modoboa. The following
functions are mandatory::
def init():
"""This function is called when Modoboa loads available and activated plugins.
Declare parameters and register events here.
"""
pass
def destroy():
"""This function is called when a plugin is disabled from the interface.
Unregister parameters and events here.
"""
pass
def infos():
"""This function is used to populate the plugins list
available in the administration panel.
It must return a dictionnary containing at least three
keys : "name", "version", "description"
"""
return {
"name" : "Example plugin",
"version" : "1.0",
"description" : "Example description"
}
def urls(prefix):
"""This function is used to update the global urls table.
It must return a sequence that corresponds to those used
inside the main ``urls.py`` file. (ie. a classical
Django construction)
:param prefix: the global url prefix (the part after the hostname)
"""
return (r'^%sexample/' % prefix, include('modoboa.extensions.example.urls'))
Once you have filled ``main.py``, simply add your plugin's name to the
``INSTALLED_APPS`` variable located inside ``settings.py``. (use the
same format as other plugins). Eventually, run ``python manage.py
syncdb`` if your plugin provides custom tables.
Events
======
Playing with events
-------------------
Modoboa provides a simple API to interact with events. It understands
two kinds of events:
* Those that return a value,
* Those that return nothing.
Listening to a specific event is achieved as follow::
from modoboa.lib import events
events.register(event, callback)
``event`` is the event's name you want to listen to, ``callback`` is
the function that will be called when this event is raised. Its
prototype must be as follow::
def callback(*args, **kwargs):
pass
It is very generic, it allows events to provide arguments if needed.
You can also stop listening to an event like this::
events.unregister(event, callback)
The parameters are the same as those used with ``register``.
Read further to get a complete list and description of the available events.
UserLogin
---------
Raised when a user logs in. This event provides a ``request`` argument
that corresponds to the ``Request`` object used inside the associated
view function.
UserLogout
----------
Raised when a user logs out. This event provides a ``request`` argument
that corresponds to the ``Request`` object used inside the associated
view function.
.. _usermenudisplay:
UserMenuDisplay
---------------
Raised when a user menu is about to be displayed. It provides a
``target`` argument that indicates which menu is being
displayed. Possible values are:
* ``uprefs_menu`` : corresponds to the menu bar available inside the *User preferences* page
* ``top_menu`` : corresponds to the top blue bar
All callbacks that listen to this event must return a list of
dictionnaries (corresponding to menu entries). Each dictionnary must
contain at least the following keys::
{"name" : "a_name_without_spaces",
"label" : _("The menu label"),
"url" : reverse("your_view"), # can be set to ""
"img" : static_url("your_pic")} # can be set to ""
AdminMenuDisplay
----------------
Raised when an admin menu is about to be displayed. It provides a
``target`` argument that indicates which menu is being
displayed. Possible values are:
* ``admin_menu_box`` : corresponds to the menu bar available inside administration pages
* ``top_menu`` : corresponds to the *Admin* dropdown menu located inside the top blue bar
See :ref:`usermenudisplay` for a description of what callbacks that
listen to this event must return.
CreateDomain
------------
Raised when a new domain is created. The new domain object is
available inside the ``dom`` argument.
DeleteDomain
------------
Raised when an existing domain is about to be deleted. The domain
object is available inside the ``dom`` argument.
CreateMailbox
-------------
Raised when a new mailbox is created. The new mailbox object is
available inside the ``mbox`` argument.
DeleteMailbox
-------------
Raised when an existing mailbox is about to be deleted. The mailbox
object is available inside the ``mbox`` argument.
ModifyMailbox
-------------
Raised when an existing mailbox is modified. The old mailbox and the
new mailbox objects are respectively available inside the ``oldmbox``
and ``mbox`` arguments.
.. _permsgettables:
PermsGetTables
--------------
Raised when the different permission lists (one per role) are about to
be displayed. The current *User* object is available inside the
``user`` argument.
Callbacks that listen to this event must return a list of
dictionnaries (corresponding to tables). Each dictionnary must contain
at least the following elements::
{"id" : "table_id",
"title" : _("The title corresponding to this table"),
"rel" : "x y",
"content" : MyPermClass().get(request)}
For ``rel``, replace x and y with the the *Add form* size (the
one that appears when you click on the ``Add permission`` button.
For ``content``, replace *MyPermClass* with the appropriate name.
.. _permsgetclass:
PermsGetClass
-------------
Raised to retrieve the class (inheriting from ``Permissions``)
implementing a specific role. This event is used to add or delete or
new instance of this role. The role's name is available inside the
``role`` argument.
Callbacks listening to this event must return the class object
corresponding to the given ``role`` argument.
ExtEnabled
----------
Raised just after an extension has been activated. The Extension
object is available inside the ``ext`` keyword argument.
ExtDisabled
-----------
Raised just after an extension has been disabled. The Extension
object is available inside the ``ext`` keyword argument.
GetAnnouncement
---------------
Some places in the interface let plugins add their own announcement
(ie. message). A keyword argument ``target`` is provided to registered
callbacks and indicates the place where the announcement will appear:
* ``loginpage`` : corresponds to the login page
Callbacks listening to this event must return a list of string.
PasswordChange
--------------
Raised just before a *password change* action. The associated ``User``
object is provided inside the ``user`` keyword argument.
Callbacks listening to this event must return a list containing either
``True`` or ``False``. If at least one ``True`` is returned, the
*password change* will be cancelled (ie. changing the password for
this user is disabled).
Parameters
==========
A plugin can declare its own parameters. There are two levels available:
* 'Administration' parameters : used to configure the plugin, editable inside the *Admin > Settings > Parameters* page,
* 'User' parameters : per-user parameters (or preferences), editable inside the *Options > Preferences* page.
Playing with parameters
-----------------------
To declare a new administration parameter, use the following function::
from modoboa.lib import parameters
parameters.register_admin(name, **kwargs)
To declare a new user parameter, use the following function::
parameter.register_user(name, **kwargs)
Both functions accept extra arguments listed here:
* ``type`` : parameter's type, possible values are : ``int``, ``string``, ``list``, ``list_yesno``,
* ``deflt`` : default value,
* ``help`` : help text,
* ``values`` : list of possible values if ``type`` is ``list``.
To undeclare parameters (for example when a plugin is disabled is
disabled from the interface), use the following function::
parameters.unregister_app(appname)
``appname`` corresponds to your plugin's name, ie. the name of the
directory containing the source code.
Custom permission levels
========================
Custom permissions roles can be added to Modoboa. If you to want to
integrate the default permissions panel (*Admin > Permissions*), each
role you add must inherit from the ``Permissions`` (file
``admin/permissions.py``) class and implement all its methods.
.. note::
See :ref:`permsgettables` and :ref:`permsgetclass` to learn how to
integrate your custom roles.