mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
WIP.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""Modoboa admin settings and events."""
|
||||
"""Modoboa admin settings."""
|
||||
|
||||
import os
|
||||
|
||||
@@ -10,43 +10,6 @@ from modoboa.lib.form_utils import YesNoField, SeparatorField
|
||||
from modoboa.lib.sysutils import exec_cmd
|
||||
from modoboa.parameters import forms as param_forms
|
||||
|
||||
from ..lib import events
|
||||
|
||||
ADMIN_EVENTS = [
|
||||
"DomainCreated",
|
||||
"DomainModified",
|
||||
"DomainDeleted",
|
||||
"DomainOwnershipRemoved",
|
||||
"GetTagsForDomain",
|
||||
|
||||
"ExtraDomainFilters",
|
||||
"ExtraDomainQsetFilters",
|
||||
"ExtraDomainTypes",
|
||||
"ExtraDomainWizardSteps",
|
||||
"GetDomainModifyLink",
|
||||
"CheckDomainName",
|
||||
|
||||
"DomainAliasCreated",
|
||||
"DomainAliasDeleted",
|
||||
|
||||
"MailboxCreated",
|
||||
"MailboxDeleted",
|
||||
"MailboxModified",
|
||||
|
||||
"MailboxAliasCreated",
|
||||
"MailboxAliasDeleted",
|
||||
|
||||
"ExtraDomainForm",
|
||||
"FillDomainInstances",
|
||||
|
||||
"ExtraAccountForm",
|
||||
"CheckExtraAccountForm",
|
||||
"FillAccountInstances",
|
||||
|
||||
"ExtraDomainImportHelp",
|
||||
"ImportObject"
|
||||
]
|
||||
|
||||
|
||||
class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
app = "admin"
|
||||
@@ -178,5 +141,3 @@ def load_admin_settings():
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", AdminParametersForm, ugettext_lazy("Administration"))
|
||||
events.declare(ADMIN_EVENTS)
|
||||
from . import callbacks
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
"""Event callbacks for modoboa admin."""
|
||||
|
||||
from modoboa.lib import events
|
||||
|
||||
from .models import (
|
||||
Domain, DomainAlias, Mailbox, Alias
|
||||
)
|
||||
@@ -11,7 +11,6 @@ from passwords.fields import PasswordField
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
from modoboa.lib import exceptions as lib_exceptions
|
||||
from modoboa.lib import fields as lib_fields
|
||||
@@ -24,6 +23,7 @@ from modoboa.lib.web_utils import render_to_json_response
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from .. import models
|
||||
from .. import signals
|
||||
|
||||
|
||||
class AccountFormGeneral(forms.ModelForm):
|
||||
@@ -460,11 +460,13 @@ class AccountForm(TabForms):
|
||||
"formtpl": "admin/permsform.html",
|
||||
"cls": AccountPermissionsForm}
|
||||
]
|
||||
cbargs = [self.user]
|
||||
cbargs = {"user": self.user}
|
||||
if "instances" in kwargs:
|
||||
cbargs += [kwargs["instances"]["general"]]
|
||||
self.forms += events.raiseQueryEvent("ExtraAccountForm", *cbargs)
|
||||
|
||||
cbargs["account"] = kwargs["instances"]["general"]
|
||||
results = signals.extra_account_forms.send(
|
||||
sender=self.__class__, **cbargs)
|
||||
self.forms += reduce(
|
||||
lambda a, b: a + b, [result[1] for result in results])
|
||||
super(AccountForm, self).__init__(request, *args, **kwargs)
|
||||
|
||||
def extra_context(self, context):
|
||||
@@ -493,9 +495,10 @@ class AccountForm(TabForms):
|
||||
return False
|
||||
return True
|
||||
|
||||
extra_forms = events.raiseQueryEvent(
|
||||
"CheckExtraAccountForm", self.account, form)
|
||||
if False in extra_forms:
|
||||
results = signals.check_extra_account_form.send(
|
||||
sender=self.__class__, account=self.account, form=form)
|
||||
results = [result[1] for result in results]
|
||||
if False in results:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -513,9 +516,6 @@ class AccountForm(TabForms):
|
||||
As forms interact with each other, it is simpler to make
|
||||
custom code to save them.
|
||||
"""
|
||||
events.raiseEvent(
|
||||
"AccountModified", self.instances["general"], self.account
|
||||
)
|
||||
self.forms[1]["instance"].save(self.user, self.account)
|
||||
if len(self.forms) <= 2:
|
||||
return
|
||||
|
||||
@@ -7,7 +7,6 @@ from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import Conflict
|
||||
from modoboa.lib.fields import DomainNameField
|
||||
from modoboa.lib.form_utils import (
|
||||
@@ -16,11 +15,13 @@ from modoboa.lib.form_utils import (
|
||||
from modoboa.lib.web_utils import render_to_json_response
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from .. import signals
|
||||
from ..lib import check_if_domain_exists
|
||||
from ..models import (
|
||||
Domain, DomainAlias, Mailbox, Alias
|
||||
)
|
||||
|
||||
|
||||
DOMAIN_TYPES = [
|
||||
("domain", _("Domain")),
|
||||
]
|
||||
@@ -60,9 +61,12 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
self.oldname = kwargs["instance"].name
|
||||
super(DomainFormGeneral, self).__init__(*args, **kwargs)
|
||||
|
||||
self.fields["type"].choices = (
|
||||
DOMAIN_TYPES + events.raiseQueryEvent("ExtraDomainTypes"))
|
||||
|
||||
extra_domain_types = reduce(
|
||||
lambda a, b: a + b,
|
||||
[result[1] for result in signals.extra_domain_types.send(
|
||||
sender=self.__class__)]
|
||||
)
|
||||
self.fields["type"].choices = DOMAIN_TYPES + extra_domain_types
|
||||
self.field_widths = {
|
||||
"quota": 3
|
||||
}
|
||||
@@ -87,8 +91,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
"""Custom fields validation.
|
||||
|
||||
We want to prevent duplicate names between domains and domain
|
||||
aliases. Extensions have the possibility to declare other
|
||||
objects (see *CheckDomainName* event).
|
||||
aliases.
|
||||
|
||||
The validation way is not very smart...
|
||||
"""
|
||||
@@ -279,11 +282,14 @@ class DomainForm(TabForms):
|
||||
"mandatory": True
|
||||
})
|
||||
|
||||
cbargs = [self.user]
|
||||
cbargs = {"user": self.user}
|
||||
if "instances" in kwargs:
|
||||
self.domain = kwargs["instances"]["general"]
|
||||
cbargs += [self.domain]
|
||||
self.forms += events.raiseQueryEvent("ExtraDomainForm", *cbargs)
|
||||
cbargs["domain"] = self.domain
|
||||
results = signals.extra_domain_forms.send(
|
||||
sender=self.__class__, **cbargs)
|
||||
self.forms += reduce(
|
||||
lambda a, b: a + b, [result[1] for result in results])
|
||||
if not self.forms:
|
||||
self.active_id = "admins"
|
||||
super(DomainForm, self).__init__(request, *args, **kwargs)
|
||||
@@ -326,8 +332,6 @@ class DomainForm(TabForms):
|
||||
f["instance"].save(self.request.user)
|
||||
|
||||
def done(self):
|
||||
if "general" in self.instances:
|
||||
events.raiseEvent("DomainModified", self.instances["general"])
|
||||
return render_to_json_response(_("Domain modified"))
|
||||
|
||||
|
||||
@@ -343,9 +347,10 @@ class DomainWizard(WizardForm):
|
||||
"admin/domain_general_form.html"
|
||||
)
|
||||
)
|
||||
steps = events.raiseQueryEvent("ExtraDomainWizardSteps")
|
||||
for step in steps:
|
||||
self.add_step(step)
|
||||
results = signals.extra_domain_wizard_steps.send(sender=self.__class__)
|
||||
for result in results:
|
||||
for step in result[1]:
|
||||
self.add_step(step)
|
||||
self.add_step(
|
||||
WizardStep(
|
||||
"options", DomainFormOptions, _("Options"),
|
||||
|
||||
@@ -94,11 +94,9 @@ def mailbox_deleted_handler(sender, **kwargs):
|
||||
It manually removes the mailbox from the aliases it is linked to
|
||||
and then remove all empty aliases.
|
||||
"""
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.permissions import ungrant_access_to_object
|
||||
|
||||
mb = kwargs["instance"]
|
||||
events.raiseEvent("MailboxDeleted", mb)
|
||||
ungrant_access_to_object(mb)
|
||||
for ralias in mb.aliasrecipient_set.select_related("alias"):
|
||||
alias = ralias.alias
|
||||
|
||||
@@ -11,11 +11,12 @@ from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import PermDeniedException
|
||||
|
||||
from .models import Domain, DomainAlias, Alias
|
||||
|
||||
from . import signals
|
||||
|
||||
|
||||
def needs_mailbox():
|
||||
"""Check if the current user owns at least one mailbox
|
||||
@@ -92,24 +93,23 @@ def get_domains(user, domfilter=None, searchquery=None, **extrafilters):
|
||||
q = Q(name__contains=searchquery)
|
||||
q |= Q(domainalias__name__contains=searchquery)
|
||||
domains = domains.filter(q).distinct()
|
||||
qset_filters = events.raiseDictEvent(
|
||||
"ExtraDomainQsetFilters", domfilter, extrafilters
|
||||
)
|
||||
if qset_filters:
|
||||
results = signals.extra_domain_qset_filters.send(
|
||||
sender="get_domains", domfilter=domfilter, extrafilters=extrafilters)
|
||||
if results:
|
||||
qset_filters = {}
|
||||
for result in results:
|
||||
qset_filters.update(result[1])
|
||||
domains = domains.filter(**qset_filters)
|
||||
return domains
|
||||
|
||||
|
||||
def check_if_domain_exists(name, extra_checks=None):
|
||||
def check_if_domain_exists(name, dtypes):
|
||||
"""Check if a domain already exists.
|
||||
|
||||
We not only look for domains, we also look for every object that
|
||||
could conflict with a domain (domain alias, etc.)
|
||||
|
||||
"""
|
||||
dtypes = events.raiseQueryEvent('CheckDomainName')
|
||||
if extra_checks is not None:
|
||||
dtypes = extra_checks + dtypes
|
||||
for dtype, label in dtypes:
|
||||
if dtype.objects.filter(name=name).exists():
|
||||
return label
|
||||
|
||||
@@ -9,10 +9,10 @@ from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import Conflict
|
||||
|
||||
from .... import lib
|
||||
from .... import signals
|
||||
|
||||
|
||||
class ImportCommand(BaseCommand):
|
||||
@@ -59,11 +59,11 @@ class ImportCommand(BaseCommand):
|
||||
try:
|
||||
fct = getattr(lib, "import_%s" % row[0].strip())
|
||||
except AttributeError:
|
||||
fct = events.raiseQueryEvent(
|
||||
"ImportObject", row[0].strip())
|
||||
fct = signals.import_object.send(
|
||||
sender=self.__class__, objtype=row[0].strip())
|
||||
if not fct:
|
||||
continue
|
||||
fct = fct[0]
|
||||
fct = fct[0][1]
|
||||
try:
|
||||
fct(superadmin, row, options)
|
||||
except Conflict:
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.permissions import (
|
||||
grant_access_to_object, ungrant_access_to_object
|
||||
)
|
||||
@@ -32,7 +31,6 @@ class AdminObject(models.Model):
|
||||
|
||||
def post_create(self, creator):
|
||||
grant_access_to_object(creator, self, is_owner=True)
|
||||
events.raiseEvent("%sCreated" % self.objectname, creator, self)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
creator = kwargs.pop("creator", None)
|
||||
@@ -41,6 +39,5 @@ class AdminObject(models.Model):
|
||||
self.post_create(creator)
|
||||
|
||||
def delete(self):
|
||||
events.raiseEvent("%sDeleted" % self.objectname, self)
|
||||
ungrant_access_to_object(self)
|
||||
super(AdminObject, self).delete()
|
||||
|
||||
@@ -15,10 +15,10 @@ from reversion import revisions as reversion
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.core.models import User, ObjectAccess
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import BadRequest, Conflict
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from .. import signals
|
||||
from .base import AdminObject
|
||||
|
||||
|
||||
@@ -89,7 +89,9 @@ class Domain(AdminObject):
|
||||
def tags(self):
|
||||
if self.type == "domain":
|
||||
return [{"name": "domain", "label": _("Domain"), "type": "dom"}]
|
||||
return events.raiseQueryEvent("GetTagsForDomain", self)
|
||||
results = signals.get_domain_tags.send(
|
||||
sender=self.__class__, domain=self)
|
||||
return reduce(lambda a, b: a + b, [result[1] for result in results])
|
||||
|
||||
@property
|
||||
def admins(self):
|
||||
@@ -153,11 +155,8 @@ class Domain(AdminObject):
|
||||
|
||||
:param User account: administrator to remove
|
||||
"""
|
||||
from modoboa.lib.permissions import \
|
||||
ungrant_access_to_object, get_object_owner
|
||||
from modoboa.lib.permissions import ungrant_access_to_object
|
||||
|
||||
if get_object_owner(self) == account:
|
||||
events.raiseEvent('DomainOwnershipRemoved', account, self)
|
||||
ungrant_access_to_object(self, account)
|
||||
for mb in self.mailbox_set.all():
|
||||
if mb.user.has_perm("admin.add_domain"):
|
||||
@@ -181,17 +180,14 @@ class Domain(AdminObject):
|
||||
from .mailbox import Quota
|
||||
|
||||
if self.domainalias_set.count():
|
||||
events.raiseEvent("DomainAliasDeleted", self.domainalias_set.all())
|
||||
ungrant_access_to_objects(self.domainalias_set.all())
|
||||
if self.alias_set.count():
|
||||
events.raiseEvent("MailboxAliasDeleted", self.alias_set.all())
|
||||
ungrant_access_to_objects(self.alias_set.all())
|
||||
if param_tools.get_global_parameter("auto_account_removal"):
|
||||
for account in User.objects.filter(mailbox__domain=self):
|
||||
account.delete(fromuser, keepdir)
|
||||
elif self.mailbox_set.count():
|
||||
Quota.objects.filter(username__contains="@%s" % self.name).delete()
|
||||
events.raiseEvent("MailboxDeleted", self.mailbox_set.all())
|
||||
ungrant_access_to_objects(self.mailbox_set.all())
|
||||
super(Domain, self).delete()
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from reversion import revisions as reversion
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib import exceptions as lib_exceptions
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
from modoboa.lib.sysutils import exec_cmd
|
||||
@@ -305,7 +304,6 @@ class Mailbox(AdminObject):
|
||||
if newaddress:
|
||||
self.rename(local_part, domain)
|
||||
self.save()
|
||||
events.raiseEvent("MailboxModified", self)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""Custom save.
|
||||
|
||||
@@ -2,14 +2,30 @@
|
||||
|
||||
import django.dispatch
|
||||
|
||||
check_extra_account_form = django.dispatch.Signal(
|
||||
providing_args=["account", "form"])
|
||||
extra_account_dashboard_widgets = django.dispatch.Signal(
|
||||
providing_args=["user", "account"])
|
||||
extra_account_forms = django.dispatch.Signal(
|
||||
providing_args=["user", "account"])
|
||||
extra_admin_content = django.dispatch.Signal(
|
||||
providing_args=["user", "location", "currentpage"])
|
||||
extra_domain_actions = django.dispatch.Signal(
|
||||
providing_args=["user", "domain"])
|
||||
extra_domain_dashboard_widgets = django.dispatch.Signal(
|
||||
providing_args=["user", "domain"])
|
||||
extra_domain_menu_entries = django.dispatch.Signal(
|
||||
providing_args=["user"])
|
||||
extra_account_dashboard_widgets = django.dispatch.Signal(
|
||||
extra_domain_filters = django.dispatch.Signal()
|
||||
extra_domain_forms = django.dispatch.Signal(providing_args=["user", "domain"])
|
||||
extra_domain_import_help = django.dispatch.Signal()
|
||||
extra_domain_menu_entries = django.dispatch.Signal(providing_args=["user"])
|
||||
extra_domain_qset_filters = django.dispatch.Signal(
|
||||
providing_args=["domfilter", "extrafilters"])
|
||||
extra_domain_types = django.dispatch.Signal()
|
||||
extra_domain_wizard_steps = django.dispatch.Signal()
|
||||
get_account_form_instances = django.dispatch.Signal(
|
||||
providing_args=["user", "account"])
|
||||
get_domain_form_instances = django.dispatch.Signal(
|
||||
providing_args=["user", "domain"])
|
||||
get_domain_tags = django.dispatch.Signal(providing_args=["domain"])
|
||||
import_object = django.dispatch.Signal(providing_args=["objtype"])
|
||||
use_external_recipients = django.dispatch.Signal(providing_args=["recipients"])
|
||||
|
||||
@@ -16,7 +16,6 @@ from reversion import revisions as reversion
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.web_utils import (
|
||||
_render_to_string, render_to_json_response
|
||||
)
|
||||
@@ -45,10 +44,13 @@ def index(request):
|
||||
)
|
||||
def _domains(request):
|
||||
sort_order, sort_dir = get_sort_order(request.GET, "name")
|
||||
extra_filters = reduce(
|
||||
lambda a, b: a + b,
|
||||
[result for result in signals.extra_domain_filters(sender="_domains")]
|
||||
)
|
||||
filters = dict(
|
||||
(flt, request.GET.get(flt, None))
|
||||
for flt in ['domfilter', 'searchquery'] +
|
||||
events.raiseQueryEvent('ExtraDomainFilters')
|
||||
for flt in ["domfilter", "searchquery"] + extra_filters
|
||||
)
|
||||
request.session['domains_filters'] = filters
|
||||
domainlist = get_domains(request.user, **filters)
|
||||
@@ -126,7 +128,10 @@ def editdomain(request, dom_id):
|
||||
raise PermDeniedException
|
||||
|
||||
instances = dict(general=domain)
|
||||
events.raiseEvent("FillDomainInstances", request.user, domain, instances)
|
||||
results = signals.get_domain_form_instances.send(
|
||||
sender="editdomain", user=request.user, domain=domain)
|
||||
for result in results:
|
||||
instances.update(result[1])
|
||||
return DomainForm(request, instances=instances).process()
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ from django.contrib.auth.decorators import (
|
||||
from reversion import revisions as reversion
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import (
|
||||
PermDeniedException, BadRequest
|
||||
)
|
||||
@@ -181,7 +180,10 @@ def editaccount(request, pk):
|
||||
mb = account.mailbox if hasattr(account, "mailbox") else None
|
||||
|
||||
instances = dict(general=account, mail=mb, perms=account)
|
||||
events.raiseEvent("FillAccountInstances", request.user, account, instances)
|
||||
results = signals.get_account_form_instances.send(
|
||||
sender="editaccount", user=request.user, account=account)
|
||||
for result in results:
|
||||
instances.update(result[1])
|
||||
return AccountForm(request, instances=instances).process()
|
||||
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@ from django.utils.translation import ugettext as _
|
||||
|
||||
from reversion import revisions as reversion
|
||||
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import ModoboaException, Conflict
|
||||
|
||||
from ..forms import ImportIdentitiesForm, ImportDataForm
|
||||
from .. import lib
|
||||
from .. import signals
|
||||
|
||||
|
||||
@reversion.create_revision()
|
||||
@@ -48,12 +48,11 @@ def importdata(request, formclass=ImportDataForm):
|
||||
try:
|
||||
fct = getattr(lib, "import_%s" % row[0].strip())
|
||||
except AttributeError:
|
||||
fct = events.raiseQueryEvent(
|
||||
'ImportObject', row[0].strip()
|
||||
)
|
||||
fct = signals.import_object.send(
|
||||
sender="importdata", objtype=row[0].strip())
|
||||
if not fct:
|
||||
continue
|
||||
fct = fct[0]
|
||||
fct = fct[0][1]
|
||||
with transaction.atomic():
|
||||
try:
|
||||
fct(request.user, row, form.cleaned_data)
|
||||
@@ -83,6 +82,8 @@ def import_domains(request):
|
||||
if request.method == "POST":
|
||||
return importdata(request)
|
||||
|
||||
results = signals.extra_domain_import_help.send(sender="import_domains")
|
||||
extra_help = reduce(lambda a, b: a + b, [result[1] for result in results])
|
||||
helptext = _("""Provide a CSV file where lines respect one of the following formats:
|
||||
<ul>
|
||||
<li><em>domain; name; quota; enabled</em></li>
|
||||
@@ -91,8 +92,7 @@ def import_domains(request):
|
||||
</ul>
|
||||
<p>The first element of each line is mandatory and must be equal to one of the previous values.</p>
|
||||
<p>You can use a different character as separator.</p>
|
||||
""" % ''.join([unicode(hlp) for hlp in
|
||||
events.raiseQueryEvent('ExtraDomainImportHelp')]))
|
||||
""") % "".join(extra_help)
|
||||
|
||||
ctx = dict(
|
||||
title=_("Import domains"),
|
||||
|
||||
@@ -4,12 +4,6 @@ from django.apps import AppConfig
|
||||
from django.db.models import signals
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
BASE_EVENTS = [
|
||||
"AccountCreated",
|
||||
|
||||
"AccountModified",
|
||||
]
|
||||
|
||||
|
||||
def load_core_settings():
|
||||
"""Load core settings.
|
||||
@@ -17,13 +11,11 @@ def load_core_settings():
|
||||
This function must be manually called (see :file:`urls.py`) in
|
||||
order to load base settings.
|
||||
"""
|
||||
from modoboa.lib import events
|
||||
from modoboa.parameters import tools as param_tools
|
||||
from .app_settings import GeneralParametersForm
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", GeneralParametersForm, ugettext_lazy("General"))
|
||||
events.declare(BASE_EVENTS)
|
||||
|
||||
|
||||
class CoreConfig(AppConfig):
|
||||
|
||||
@@ -20,7 +20,6 @@ import jsonfield
|
||||
from reversion import revisions as reversion
|
||||
|
||||
from modoboa.core.password_hashers import get_password_hasher
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.exceptions import (
|
||||
PermDeniedException, InternalError, BadRequest, Conflict
|
||||
)
|
||||
@@ -330,7 +329,6 @@ class User(PermissionsMixin):
|
||||
"""Grant permission on this user to creator."""
|
||||
from modoboa.lib.permissions import grant_access_to_object
|
||||
grant_access_to_object(creator, self, is_owner=True)
|
||||
events.raiseEvent("AccountCreated", self)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
creator = kwargs.pop("creator", None)
|
||||
|
||||
@@ -36,3 +36,4 @@ user_can_set_role = django.dispatch.Signal(
|
||||
providing_args=["user", "role", "account"])
|
||||
user_login = django.dispatch.Signal(
|
||||
providing_args=["username", "password"])
|
||||
user_logout = django.dispatch.Signal()
|
||||
|
||||
@@ -12,7 +12,6 @@ from django.views.decorators.cache import never_cache
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
|
||||
from modoboa.core.forms import LoginForm
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.web_utils import _render_to_string
|
||||
|
||||
from .base import find_nextlocation
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
:mod:`EVENTS` --- simple EVENTS handling
|
||||
----------------------------------------
|
||||
|
||||
This module provides a simple way of managing EVENTS between Modoboa
|
||||
core application and additional components.
|
||||
|
||||
"""
|
||||
|
||||
EVENTS = []
|
||||
CALLBACKS = {}
|
||||
|
||||
|
||||
def declare(nevents):
|
||||
"""Declare new events.
|
||||
|
||||
:param list nevents: a list of event names
|
||||
"""
|
||||
for evt in nevents:
|
||||
if evt not in EVENTS:
|
||||
EVENTS.append(evt)
|
||||
|
||||
|
||||
def register(event, callback):
|
||||
"""Register a plugin callback for a specific event
|
||||
|
||||
The event must be declared in this module.
|
||||
|
||||
:param event: the event to listen to
|
||||
:param callback: a function to execute when the event is raised
|
||||
"""
|
||||
# if not event in EVENTS:
|
||||
# print "Event %s not registered" % event
|
||||
# return 0
|
||||
if event not in CALLBACKS.keys():
|
||||
CALLBACKS[event] = {}
|
||||
fullname = "%s.%s" % (callback.__module__, callback.__name__)
|
||||
if fullname not in CALLBACKS[event]:
|
||||
CALLBACKS[event][fullname] = callback
|
||||
return 1
|
||||
|
||||
|
||||
class observe(object):
|
||||
"""Event observing decorator.
|
||||
|
||||
Automatically register the decorated function to observe the given
|
||||
event.
|
||||
|
||||
:param evtnames: a list of event names
|
||||
"""
|
||||
def __init__(self, *evtnames, **kwargs):
|
||||
self.evtnames = evtnames
|
||||
|
||||
def __call__(self, f):
|
||||
for evt in self.evtnames:
|
||||
register(evt, f)
|
||||
return f
|
||||
|
||||
|
||||
def unregister(event, callback):
|
||||
"""Unregister a callback for a specific event
|
||||
|
||||
:param event: the targeted event
|
||||
:param callback: the callback to remove
|
||||
"""
|
||||
if event not in EVENTS:
|
||||
return False
|
||||
if event not in CALLBACKS:
|
||||
return False
|
||||
fullname = "%s.%s" % (callback.__module__, callback.__name__)
|
||||
try:
|
||||
del CALLBACKS[event][fullname]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def raiseEvent(event, *args, **kwargs):
|
||||
"""Raise a specific event
|
||||
|
||||
Any additional keyword argument will be passed to registered
|
||||
CALLBACKS.
|
||||
|
||||
:param event: the event to raise
|
||||
"""
|
||||
if event not in EVENTS or event not in CALLBACKS:
|
||||
return 0
|
||||
for callback in CALLBACKS[event].values():
|
||||
callback(*args, **kwargs)
|
||||
return 1
|
||||
|
||||
|
||||
def raiseQueryEvent(event, *args, **kwargs):
|
||||
"""Raise a specific event and wait for answers from CALLBACKS
|
||||
|
||||
Any additional keyword argument will be passed to registered
|
||||
CALLBACKS. Callback answers are returned as a list.
|
||||
|
||||
:param event: the event to raise
|
||||
"""
|
||||
result = []
|
||||
if event not in EVENTS or event not in CALLBACKS:
|
||||
return result
|
||||
for callback in CALLBACKS[event].values():
|
||||
tmp = callback(*args, **kwargs)
|
||||
if tmp is None:
|
||||
# Callback is registered but associated extension is
|
||||
# disabled.
|
||||
continue
|
||||
result += tmp
|
||||
return result
|
||||
|
||||
|
||||
def raiseDictEvent(event, *args):
|
||||
"""Raise a specific event and return result as a dictionnary
|
||||
|
||||
Any additional keyword argument will be passed to registered
|
||||
CALLBACKS. Callback answers must be dictionnaries.
|
||||
|
||||
:param event: the event to raise
|
||||
:return: a dictionnary
|
||||
"""
|
||||
result = {}
|
||||
if event not in EVENTS or event not in CALLBACKS:
|
||||
return result
|
||||
for callback in CALLBACKS[event].values():
|
||||
tmp = callback(*args)
|
||||
if tmp is None:
|
||||
# Callback is registered but associated extension is
|
||||
# disabled.
|
||||
continue
|
||||
for k, v in tmp.iteritems():
|
||||
result[k] = v
|
||||
return result
|
||||
@@ -3,20 +3,13 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
EVENTS = [
|
||||
"GetExtraLimitTemplates"
|
||||
]
|
||||
|
||||
|
||||
def load_limits_settings():
|
||||
"""Load settings."""
|
||||
from modoboa.lib import events
|
||||
from modoboa.parameters import tools as param_tools
|
||||
from .app_settings import ParametersForm
|
||||
|
||||
param_tools.registry.add("global", ParametersForm, _("Limits"))
|
||||
events.declare(EVENTS)
|
||||
from . import general_callbacks
|
||||
|
||||
|
||||
class LimitsConfig(AppConfig):
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
"""General event callbacks."""
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.lib import events
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from . import forms
|
||||
from . import utils
|
||||
|
||||
|
||||
@events.observe("ExtraAccountForm")
|
||||
def extra_account_form(user, account=None):
|
||||
if not param_tools.get_global_parameter("enable_admin_limits"):
|
||||
return []
|
||||
if user.role not in ["SuperAdmins", "Resellers"]:
|
||||
return []
|
||||
condition = (
|
||||
(account is not None and
|
||||
account.role not in ["Resellers", "DomainAdmins"]) or
|
||||
user == account
|
||||
)
|
||||
if condition:
|
||||
return []
|
||||
|
||||
return [{
|
||||
"id": "resources", "title": _("Resources"),
|
||||
"cls": forms.ResourcePoolForm
|
||||
}]
|
||||
|
||||
|
||||
@events.observe("ExtraDomainForm")
|
||||
def extra_domain_form(user, domain):
|
||||
"""Include domain limits form."""
|
||||
if not param_tools.get_global_parameter("enable_domain_limits"):
|
||||
return []
|
||||
if not user.has_perm("admin.change_domain"):
|
||||
return []
|
||||
return [{
|
||||
"id": "resources", "title": _("Resources"),
|
||||
"cls": forms.DomainLimitsForm
|
||||
}]
|
||||
|
||||
|
||||
@events.observe("FillDomainInstances")
|
||||
def fill_domain_instances(user, domain, instances):
|
||||
"""Set domain instance for resources form."""
|
||||
if not param_tools.get_global_parameter("enable_domain_limits"):
|
||||
return
|
||||
if not user.has_perm("admin.change_domain"):
|
||||
return
|
||||
instances["resources"] = domain
|
||||
|
||||
|
||||
@events.observe("CheckExtraAccountForm")
|
||||
def check_form_access(account, form):
|
||||
if form["id"] != "resources":
|
||||
return [True]
|
||||
if account.role not in ["Resellers", "DomainAdmins"]:
|
||||
return [False]
|
||||
return [True]
|
||||
|
||||
|
||||
@events.observe("FillAccountInstances")
|
||||
def fill_account_instances(user, account, instances):
|
||||
condition = (
|
||||
not param_tools.get_global_parameter("enable_admin_limits") or
|
||||
(not user.is_superuser and user.role != "Resellers")
|
||||
)
|
||||
if condition:
|
||||
return
|
||||
if account.role not in ["Resellers", "DomainAdmins"]:
|
||||
return
|
||||
instances["resources"] = account
|
||||
@@ -5,6 +5,7 @@ from django.dispatch import receiver
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.admin import signals as admin_signals
|
||||
@@ -14,6 +15,7 @@ from modoboa.lib import signals as lib_signals
|
||||
from modoboa.lib import permissions
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from . import forms
|
||||
from . import lib
|
||||
from . import models
|
||||
from . import utils
|
||||
@@ -103,6 +105,74 @@ def display_admin_limits(sender, user, account, **kwargs):
|
||||
}]
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_account_forms)
|
||||
def extra_account_form(sender, user, account=None, **kwargs):
|
||||
"""Add limits form."""
|
||||
if not param_tools.get_global_parameter("enable_admin_limits"):
|
||||
return []
|
||||
if user.role not in ["SuperAdmins", "Resellers"]:
|
||||
return []
|
||||
condition = (
|
||||
(account is not None and
|
||||
account.role not in ["Resellers", "DomainAdmins"]) or
|
||||
user == account
|
||||
)
|
||||
if condition:
|
||||
return []
|
||||
return [{
|
||||
"id": "resources", "title": _("Resources"),
|
||||
"cls": forms.ResourcePoolForm
|
||||
}]
|
||||
|
||||
|
||||
@receiver(admin_signals.check_extra_account_form)
|
||||
def check_form_access(sender, account, form, **kwargs):
|
||||
"""Check if form must be used for account."""
|
||||
if form["id"] != "resources":
|
||||
return True
|
||||
if account.role not in ["Resellers", "DomainAdmins"]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@receiver(admin_signals.get_account_form_instances)
|
||||
def fill_account_instances(sender, user, account, **kwargs):
|
||||
"""Set account instance for resources form."""
|
||||
condition = (
|
||||
not param_tools.get_global_parameter("enable_admin_limits") or
|
||||
(not user.is_superuser and user.role != "Resellers") or
|
||||
account.role not in ["Resellers", "DomainAdmins"]
|
||||
)
|
||||
if condition:
|
||||
return {}
|
||||
return {"resources": account}
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_domain_forms)
|
||||
def extra_domain_form(sender, user, domain, **kwargs):
|
||||
"""Include domain limits form."""
|
||||
if not param_tools.get_global_parameter("enable_domain_limits"):
|
||||
return []
|
||||
if not user.has_perm("admin.change_domain"):
|
||||
return []
|
||||
return [{
|
||||
"id": "resources", "title": _("Resources"),
|
||||
"cls": forms.DomainLimitsForm
|
||||
}]
|
||||
|
||||
|
||||
@receiver(admin_signals.get_domain_form_instances)
|
||||
def fill_domain_instances(sender, user, domain, **kwargs):
|
||||
"""Set domain instance for resources form."""
|
||||
condition = (
|
||||
not param_tools.get_global_parameter("enable_domain_limits") or
|
||||
not user.has_perm("admin.change_domain")
|
||||
)
|
||||
if condition:
|
||||
return {}
|
||||
return {"resources": domain}
|
||||
|
||||
|
||||
@receiver(core_signals.account_deleted)
|
||||
def move_resource(sender, user, **kwargs):
|
||||
"""Move remaining resource to another user."""
|
||||
|
||||
@@ -5,7 +5,6 @@ from . import constants
|
||||
|
||||
def get_user_limit_templates():
|
||||
"""Return defined templates."""
|
||||
# FIXME: change GetExtraLimitTemplates
|
||||
return constants.DEFAULT_USER_LIMITS.items()
|
||||
|
||||
|
||||
|
||||
@@ -3,26 +3,13 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
EVENTS = [
|
||||
"RelayDomainCreated",
|
||||
"RelayDomainDeleted",
|
||||
"RelayDomainModified",
|
||||
"RelayDomainAliasCreated",
|
||||
"RelayDomainAliasDeleted",
|
||||
"ExtraRelayDomainForm",
|
||||
"FillRelayDomainInstances"
|
||||
]
|
||||
|
||||
|
||||
def load_relaydomains_settings():
|
||||
"""Load application settings."""
|
||||
from modoboa.parameters import tools as param_tools
|
||||
from modoboa.lib import events
|
||||
from .app_settings import AdminParametersForm
|
||||
|
||||
param_tools.registry.add("global", AdminParametersForm, _("Relay domains"))
|
||||
events.declare(EVENTS)
|
||||
from . import general_callbacks
|
||||
|
||||
|
||||
class RelayDomainsConfig(AppConfig):
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
"""General event callbacks."""
|
||||
|
||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||
|
||||
from modoboa.lib import events
|
||||
|
||||
from .forms import RelayDomainWizardStep, RelayDomainFormGeneral
|
||||
|
||||
|
||||
@events.observe('ExtraDomainFilters')
|
||||
def extra_domain_filters():
|
||||
return ['srvfilter']
|
||||
|
||||
|
||||
@events.observe("ExtraDomainTypes")
|
||||
def extra_domain_types():
|
||||
"""Declare the relay domain type."""
|
||||
return [("relaydomain", _("Relay domain"))]
|
||||
|
||||
|
||||
@events.observe("ExtraDomainWizardSteps")
|
||||
def extra_wizard_step():
|
||||
"""Return a step to configure the relay settings."""
|
||||
return [RelayDomainWizardStep(
|
||||
"relay", RelayDomainFormGeneral, _("Relay domain"),
|
||||
"relaydomains/relaydomain_form.html"
|
||||
)]
|
||||
|
||||
|
||||
@events.observe("ExtraDomainForm")
|
||||
def extra_domain_form(user, domain):
|
||||
"""Return relay settings for domain edition."""
|
||||
if not user.has_perm("relaydomains.change_relaydomain"):
|
||||
return []
|
||||
if domain.type != "relaydomain":
|
||||
return []
|
||||
return [{
|
||||
"id": "relaydomain", "title": _("Relay settings"),
|
||||
"cls": RelayDomainFormGeneral,
|
||||
"formtpl": "relaydomains/relaydomain_form.html"
|
||||
}]
|
||||
|
||||
|
||||
@events.observe("FillDomainInstances")
|
||||
def fill_domain_instances(user, domain, instances):
|
||||
"""Fill the relaydomain form with the right instance."""
|
||||
if not user.has_perm("relaydomains.change_relaydomain"):
|
||||
return
|
||||
if domain.type != "relaydomain":
|
||||
return
|
||||
instances["relaydomain"] = domain.relaydomain
|
||||
|
||||
|
||||
@events.observe("ExtraDomainQsetFilters")
|
||||
def extra_domain_entries(domfilter, extrafilters):
|
||||
"""Return extra queryset filters."""
|
||||
if domfilter is not None and domfilter and domfilter != 'relaydomain':
|
||||
return {}
|
||||
if "srvfilter" in extrafilters and extrafilters["srvfilter"]:
|
||||
return {"relaydomain__service__name": extrafilters["srvfilter"]}
|
||||
return {}
|
||||
|
||||
|
||||
@events.observe("GetTagsForDomain")
|
||||
def get_tags_for_domain(domain):
|
||||
"""Return relay domain custom tags."""
|
||||
if domain.type != "relaydomain":
|
||||
return []
|
||||
return domain.relaydomain.tags
|
||||
|
||||
|
||||
@events.observe('ExtraDomainImportHelp')
|
||||
def extra_domain_import_help():
|
||||
return [ugettext_lazy("""
|
||||
<li><em>relaydomain; name; target host; service; enabled; verify recipients</em></li>
|
||||
""")]
|
||||
|
||||
|
||||
@events.observe('ImportObject')
|
||||
def get_import_func(objtype):
|
||||
from .lib import import_relaydomain
|
||||
|
||||
if objtype == 'relaydomain':
|
||||
return [import_relaydomain]
|
||||
return []
|
||||
@@ -4,18 +4,21 @@ from django.conf import settings
|
||||
from django.db.models import signals
|
||||
from django.dispatch import receiver
|
||||
from django.template import Template, Context
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.admin.signals import use_external_recipients
|
||||
from modoboa.admin import signals as admin_signals
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
|
||||
from . import constants
|
||||
from . import forms
|
||||
from . import lib
|
||||
from . import models
|
||||
from . import postfix_maps
|
||||
|
||||
|
||||
@receiver(use_external_recipients)
|
||||
@receiver(admin_signals.use_external_recipients)
|
||||
def check_relaydomain_alias(sender, **kwargs):
|
||||
"""Allow the creation of an alias on a relaydomain."""
|
||||
recipient = kwargs.get("recipients")
|
||||
@@ -78,3 +81,85 @@ def static_content(sender, caller, st_type, user, **kwargs):
|
||||
</script>
|
||||
""")
|
||||
return [t.render(Context({"STATIC_URL": settings.STATIC_URL}))]
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_domain_filters)
|
||||
def extra_domain_filters(sender, **kwargs):
|
||||
"""Return relaydomain filters."""
|
||||
return ["srvfilter"]
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_domain_forms)
|
||||
def extra_domain_form(sender, user, **kwargs):
|
||||
"""Return relay settings for domain edition."""
|
||||
if not user.has_perm("relaydomains.change_relaydomain"):
|
||||
return []
|
||||
domain = kwargs.get("domain")
|
||||
if not domain or domain.type != "relaydomain":
|
||||
return []
|
||||
return [{
|
||||
"id": "relaydomain", "title": _("Relay settings"),
|
||||
"cls": forms.RelayDomainFormGeneral,
|
||||
"formtpl": "relaydomains/relaydomain_form.html"
|
||||
}]
|
||||
|
||||
|
||||
@receiver(admin_signals.get_domain_form_instances)
|
||||
def fill_domain_instances(sender, user, domain, **kwargs):
|
||||
"""Fill the relaydomain form with the right instance."""
|
||||
condition = (
|
||||
not user.has_perm("relaydomains.change_relaydomain") or
|
||||
domain.type != "relaydomain"
|
||||
)
|
||||
if condition:
|
||||
return {}
|
||||
return {"relaydomain": domain.relaydomain}
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_domain_import_help)
|
||||
def extra_domain_import_help(sender, **kwargs):
|
||||
"""Add extra help lines."""
|
||||
return [_("""
|
||||
<li><em>relaydomain; name; target host; service; enabled; verify recipients</em></li>
|
||||
""")]
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_domain_qset_filters)
|
||||
def extra_domain_entries(sender, domfilter, extrafilters, **kwargs):
|
||||
"""Return extra queryset filters."""
|
||||
if domfilter is not None and domfilter and domfilter != "relaydomain":
|
||||
return {}
|
||||
if "srvfilter" in extrafilters and extrafilters["srvfilter"]:
|
||||
return {"relaydomain__service__name": extrafilters["srvfilter"]}
|
||||
return {}
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_domain_types)
|
||||
def extra_domain_types(sender, **kwargs):
|
||||
"""Declare the relay domain type."""
|
||||
return [("relaydomain", _("Relay domain"))]
|
||||
|
||||
|
||||
@receiver(admin_signals.extra_domain_wizard_steps)
|
||||
def extra_wizard_step(sender, **kwargs):
|
||||
"""Return a step to configure the relay settings."""
|
||||
return [forms.RelayDomainWizardStep(
|
||||
"relay", forms.RelayDomainFormGeneral, _("Relay domain"),
|
||||
"relaydomains/relaydomain_form.html"
|
||||
)]
|
||||
|
||||
|
||||
@receiver(admin_signals.get_domain_tags)
|
||||
def get_tags_for_domain(sender, domain, **kwargs):
|
||||
"""Return relay domain custom tags."""
|
||||
if domain.type != "relaydomain":
|
||||
return []
|
||||
return domain.relaydomain.tags
|
||||
|
||||
|
||||
@receiver(admin_signals.import_object)
|
||||
def get_import_func(sender, objtype, **kwargs):
|
||||
"""Return function used to import objtype."""
|
||||
if objtype == "relaydomain":
|
||||
return [lib.import_relaydomain]
|
||||
return []
|
||||
|
||||
Reference in New Issue
Block a user