This commit is contained in:
Antoine Nguyen
2016-11-23 11:31:57 +01:00
parent 9ee200ea5b
commit 5480a96a73
26 changed files with 246 additions and 446 deletions
+1 -40
View File
@@ -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
-7
View File
@@ -1,7 +0,0 @@
"""Event callbacks for modoboa admin."""
from modoboa.lib import events
from .models import (
Domain, DomainAlias, Mailbox, Alias
)
+11 -11
View File
@@ -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
+19 -14
View File
@@ -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"),
-2
View File
@@ -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
+9 -9
View File
@@ -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
View File
@@ -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()
+5 -9
View File
@@ -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()
-2
View File
@@ -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.
+19 -3
View File
@@ -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"])
+9 -4
View File
@@ -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()
+4 -2
View File
@@ -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()
+7 -7
View File
@@ -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"),
-8
View File
@@ -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):
-2
View File
@@ -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)
+1
View File
@@ -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()
-1
View File
@@ -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
-135
View File
@@ -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
-7
View File
@@ -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):
-75
View File
@@ -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
+70
View File
@@ -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."""
-1
View File
@@ -5,7 +5,6 @@ from . import constants
def get_user_limit_templates():
"""Return defined templates."""
# FIXME: change GetExtraLimitTemplates
return constants.DEFAULT_USER_LIMITS.items()
-13
View File
@@ -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):
-85
View File
@@ -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 []
+87 -2
View File
@@ -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 []