From 69440e512f718139bb58dacaf743f780920e5ef1 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 4 Jul 2012 10:16:14 +0200 Subject: [PATCH] New layout. Not the prettiest one but we need to release something :p We'll do better for a future version. see #260 --- doc/extending/events.rst | 12 +++ modoboa/admin/views.py | 6 +- modoboa/extensions/amavis/__init__.py | 87 ++++++++----------- modoboa/extensions/amavis/forms.py | 71 +++++++-------- modoboa/extensions/amavis/models.py | 29 +++++-- .../amavis/domain_content_filter.html | 8 +- modoboa/lib/events.py | 1 + 7 files changed, 114 insertions(+), 100 deletions(-) diff --git a/doc/extending/events.rst b/doc/extending/events.rst index a55518d9c..deadd3f63 100644 --- a/doc/extending/events.rst +++ b/doc/extending/events.rst @@ -200,6 +200,18 @@ Raised when an existing domain alias is about to be deleted. * ``domain_alias`` is a ``DomainAlias`` instance +DomainModified +============== + +Raised when a domain has been modified. + +*Callback prototype*:: + + def callback(domain): pass + +* ``domain`` is the modified ``Domain`` instance, it contains an extra + ``oldname`` field which contains the old domain name + ExtDisabled =========== diff --git a/modoboa/admin/views.py b/modoboa/admin/views.py index 36ea3cffd..a300bfb1f 100644 --- a/modoboa/admin/views.py +++ b/modoboa/admin/views.py @@ -114,9 +114,13 @@ def editdomain(request, dom_id, tplname="admin/editdomainform.html"): "formid" : "domform", "domain" : domain} if request.method == "POST": + def editdomain_cb(user, newdomain): + events.raiseEvent("DomainModified", domain) + + domain.oldname = domain.name form = DomainForm(request.user, request.POST, instances=instances) return _validate_domain(request, form, _("Domain modified"), commonctx, tplname, - tpl_form_name="tabs") + tpl_form_name="tabs", callback=editdomain_cb) commonctx["tabs"] = DomainForm(request.user, instances=instances) commonctx["domadmins"] = domadmins diff --git a/modoboa/extensions/amavis/__init__.py b/modoboa/extensions/amavis/__init__.py index 07e6a0cf9..57c9d78fb 100644 --- a/modoboa/extensions/amavis/__init__.py +++ b/modoboa/extensions/amavis/__init__.py @@ -1,6 +1,11 @@ # coding: utf-8 """ -Amavis quarantine manager (SQL based) +Amavis management frontend. + +Provides: + +* SQL quarantine management +* Per-domain settings """ from django.utils.translation import ugettext as _, ugettext_lazy @@ -20,22 +25,18 @@ class Amavis(ModoExtension): """Init function Only run once, when the extension is enabled. We create records - for existing mailboxes in order Amavis considers them local. + for existing domains to let Amavis consider them local. """ - from modoboa.admin.models import Mailbox - from models import Users + from modoboa.admin.models import Domain + from models import Users, Policy - for mb in Mailbox.objects.all(): + for dom in Domain.objects.all(): try: - u = Users.objects.get(email=mb.full_address) + u = Users.objects.get(email="@%s" % dom.name) except Users.DoesNotExist: - u = Users() - u.email = mb.full_address - u.fullname = mb.user.fullname - u.local = "1" - u.priority = 7 - u.policy_id = 1 - u.save() + p = Policy.objects.create(policy_name=dom.name) + Users.objects.create(email="@%s" % dom.name, fullname=dom.name, + local="1", priority=7, policy=p) def load(self): parameters.register_admin( @@ -76,9 +77,9 @@ class Amavis(ModoExtension): help=ugettext_lazy("Sets the maximum number of messages displayed in a page") ) - def destroy(self): - events.unregister("UserMenuDisplay", menu) - parameters.unregister_app("amavis") + def destroy(self): + events.unregister("UserMenuDisplay", menu) + parameters.unregister_app("amavis") exts_pool.register_extension(Amavis) @@ -94,6 +95,24 @@ def menu(target, user): ] return [] +@events.observe("CreateDomain") +def on_create_domain(user, domain): + from models import Users, Policy + p = Policy.objects.create(policy_name=domain.name) + Users.objects.create(email="@%s" % domain.name, fullname=domain.name, + local="1", priority=7, policy=p) + +@events.observe("DomainModified") +def on_domain_modified(domain): + if domain.oldname != domain.name: + from models import Users + u = Users.objects.get(email="@%s" % domain.oldname) + u.email = "@%s" % domain.name + u.fullname = domain.name + u.policy.policy_name = domain.name + u.policy.save() + u.save() + @events.observe("DeleteDomain") def on_delete_domain(domain): from models import Users @@ -105,42 +124,6 @@ def on_delete_domain(domain): u.policy.delete() u.delete() -@events.observe("CreateMailbox") -def create_user_record(user, mailbox): - from models import Users - - try: - Users.objects.get(email=mailbox.full_address) - except Users.DoesNotExist: - u = Users() - u.email = mailbox.full_address - u.fullname = mailbox.user.fullname - u.local = "1" - u.priority = 7 - u.policy_id = 1 - u.save() - -@events.observe("ModifyMailbox") -def modify_user_record(mailbox, oldmailbox): - if mailbox.full_address == oldmailbox.full_address: - return - u = Users.objects.get(email=oldmailbox.full_address) - u.email = mailbox.full_address - u.save() - -@events.observe("DeleteMailbox") -def remove_user_record(mailboxes): - from models import Users - from modoboa.admin.models import Mailbox - - if isinstance(mailboxes, Mailbox): - mailboxes = [mailboxes] - for mailbox in mailboxes: - try: - Users.objects.get(email=mailbox.full_address).delete() - except Users.DoesNotExist: - pass - @events.observe("GetStaticContent") def extra_static_content(user): if parameters.get_admin("USER_CAN_RELEASE") == "yes" \ diff --git a/modoboa/extensions/amavis/forms.py b/modoboa/extensions/amavis/forms.py index 231fe2cb5..e59f75339 100644 --- a/modoboa/extensions/amavis/forms.py +++ b/modoboa/extensions/amavis/forms.py @@ -3,38 +3,32 @@ from django import forms from models import Policy, Users from django.utils.translation import ugettext_lazy +from django.forms.widgets import RadioSelect, RadioInput +from django.utils.html import conditional_escape +from django.utils.encoding import force_unicode +from django.utils.safestring import mark_safe -def is_yes(v): return v == 'Y' +class CustomRadioInput(RadioInput): + def __unicode__(self): + if 'id' in self.attrs: + label_for = ' for="%s_%s"' % (self.attrs['id'], self.index) + else: + label_for = '' + choice_label = conditional_escape(force_unicode(self.choice_label)) + return mark_safe(u'' % (label_for, self.tag(), choice_label)) -class CustomInputField(forms.CharField): - """Custom field +class InlineRadioRenderer(RadioSelect.renderer): + def __iter__(self): + for i, choice in enumerate(self.choices): + yield CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, i) - Most of the columns defined by amavis use the *char* type even if - they only support 2 values (Y/N). As we want to display them using - checkboxes, we need to make some modifications in order that - values are correctly interpreted. - """ - def validate(self, value): - value = "N" if not value else "Y" - super(CustomInputField, self).validate(value) + def render(self): + return mark_safe(u'\n'.join([u'%s\n' % force_unicode(w) for w in self])) - def clean(self, value): - value = "N" if not value else "Y" - return super(CustomInputField, self).clean(value) +class InlineRadioSelect(RadioSelect): + renderer = InlineRadioRenderer class DomainPolicyForm(forms.ModelForm): - bypass_spam_checks = CustomInputField(label=ugettext_lazy("Spam filter"), - widget=forms.CheckboxInput(check_test=is_yes), - help_text=ugettext_lazy("enabled")) - bypass_virus_checks = CustomInputField(label=ugettext_lazy("Virus filter"), - widget=forms.CheckboxInput(check_test=is_yes), - help_text=ugettext_lazy("enabled")) - bypass_banned_checks = CustomInputField(label=ugettext_lazy("Banned filter"), - widget=forms.CheckboxInput(check_test=is_yes), - help_text=ugettext_lazy("enabled")) - spam_modifies_subj = CustomInputField(label=ugettext_lazy("Spam marker"), - widget=forms.CheckboxInput(check_test=is_yes), - help_text=ugettext_lazy("tag subject")) class Meta: model = Policy @@ -42,8 +36,12 @@ class DomainPolicyForm(forms.ModelForm): 'spam_tag2_level', 'spam_modifies_subj', 'spam_kill_level', 'bypass_banned_checks') widgets = { + 'bypass_virus_checks' : InlineRadioSelect(), + 'bypass_spam_checks' : InlineRadioSelect(), 'spam_tag2_level' : forms.TextInput(attrs={'class' : 'span1'}), + 'spam_modifies_subj' : InlineRadioSelect(), 'spam_kill_level' : forms.TextInput(attrs={'class' : 'span1'}), + 'bypass_banned_checks' : InlineRadioSelect(), } def __init__(self, *args, **kwargs): @@ -55,20 +53,17 @@ class DomainPolicyForm(forms.ModelForm): except (Users.DoesNotExist, Policy.DoesNotExist), e: del kwargs["instance"] super(DomainPolicyForm, self).__init__(*args, **kwargs) - + for f in self.fields.keys(): + self.fields[f].required = False + def save(self, user, commit=True): p = super(DomainPolicyForm, self).save(commit=False) if commit: - p.save() - try: - u = Users.objects.get(policy__id=p.id) - except Users.DoesNotExist: - u = Users() - u.email = "@%s" % self.domain.name - u.fullname = self.domain.name - u.policy = p - u.local = "1" - u.priority = 7 - u.save() p.save() + try: + u = Users.objects.get(policy=p) + except Users.DoesNotExist: + u = Users.objects.get(email="@%s" % self.domain.name) + u.policy = p + p.save() return p diff --git a/modoboa/extensions/amavis/models.py b/modoboa/extensions/amavis/models.py index 359a0f449..411007109 100644 --- a/modoboa/extensions/amavis/models.py +++ b/modoboa/extensions/amavis/models.py @@ -69,17 +69,36 @@ class Msgrcpt(models.Model): unique_together = ("mail", "rid") class Policy(models.Model): - id = models.AutoField(primary_key=True) policy_name = models.CharField(max_length=96, blank=True) virus_lover = models.CharField(max_length=3, blank=True) spam_lover = models.CharField(max_length=3, blank=True) banned_files_lover = models.CharField(max_length=3, blank=True) bad_header_lover = models.CharField(max_length=3, blank=True) - bypass_virus_checks = models.CharField(max_length=3, blank=True) - bypass_spam_checks = models.CharField(max_length=3, blank=True) - bypass_banned_checks = models.CharField(max_length=3, blank=True) + bypass_virus_checks = models.CharField( + ugettext_lazy("Virus filter"), default='', + choices=(('Y', 'yes'), ('N', 'no'), ('', 'default')), + max_length=3, + help_text=ugettext_lazy("Bypass virus checks or not. Choose 'default' to use global settings.") + ) + bypass_spam_checks = models.CharField( + ugettext_lazy("Spam filter"), default='', + choices=(('Y', 'yes'), ('N', 'no'), ('', 'default')), + max_length=3, + help_text=ugettext_lazy("Bypass spam checks or not. Choose 'default' to use global settings.") + ) + bypass_banned_checks = models.CharField( + ugettext_lazy("Banned filter"), default='', + choices=(('Y', 'yes'), ('N', 'no'), ('', 'default')), + max_length=3, + help_text=ugettext_lazy("Bypass banned checks or not. Choose 'default' to use global settings.") + ) bypass_header_checks = models.CharField(max_length=3, blank=True) - spam_modifies_subj = models.CharField(max_length=3, blank=True) + spam_modifies_subj = models.CharField( + ugettext_lazy("Spam marker"), default='', + choices=(('Y', 'yes'), ('N', 'no'), ('', 'default')), + max_length=3, + help_text=ugettext_lazy("Modify spam subject or not. Choose 'default' to use global settings.") + ) virus_quarantine_to = models.CharField(max_length=192, blank=True) spam_quarantine_to = models.CharField(max_length=192, blank=True) banned_quarantine_to = models.CharField(max_length=192, blank=True) diff --git a/modoboa/extensions/amavis/templates/amavis/domain_content_filter.html b/modoboa/extensions/amavis/templates/amavis/domain_content_filter.html index 727b8c5e5..7294ac62a 100644 --- a/modoboa/extensions/amavis/templates/amavis/domain_content_filter.html +++ b/modoboa/extensions/amavis/templates/amavis/domain_content_filter.html @@ -1,6 +1,6 @@ {% load i18n libextras %} -{% render_field form.bypass_virus_checks "inline" %} -{% render_field form.bypass_spam_checks "inline" %} +{% render_field form.bypass_virus_checks %} +{% render_field form.bypass_spam_checks %}
@@ -8,5 +8,5 @@ {{ form.spam_kill_level }} {% trans "or more throw spam message away" %}
-{% render_field form.spam_modifies_subj "inline" %} -{% render_field form.bypass_banned_checks "inline" %} +{% render_field form.spam_modifies_subj %} +{% render_field form.bypass_banned_checks %} diff --git a/modoboa/lib/events.py b/modoboa/lib/events.py index f952b2826..b69844dc2 100644 --- a/modoboa/lib/events.py +++ b/modoboa/lib/events.py @@ -17,6 +17,7 @@ events = [ "CanCreate", "CreateDomain", + "DomainModified", "DeleteDomain", "DomainAliasCreated",