diff --git a/admin/forms.py b/admin/forms.py index 0d296b7e0..a4127713c 100644 --- a/admin/forms.py +++ b/admin/forms.py @@ -10,7 +10,7 @@ from modoboa.lib.permissions import get_account_roles from modoboa.lib.formutils import * from modoboa.lib.permissions import * -class DomainForm(forms.ModelForm, DynamicForm): +class DomainFormGeneral(forms.ModelForm, DynamicForm): aliases = DomainNameField( label=ugettext_lazy("Alias(es)"), required=False, @@ -25,7 +25,7 @@ class DomainForm(forms.ModelForm, DynamicForm): self.oldname = None if kwargs.has_key("instance"): self.oldname = kwargs["instance"].name - super(DomainForm, self).__init__(*args, **kwargs) + super(DomainFormGeneral, self).__init__(*args, **kwargs) if len(args) and isinstance(args[0], QueryDict): self._load_from_qdict(args[0], "aliases", DomainNameField) @@ -36,7 +36,7 @@ class DomainForm(forms.ModelForm, DynamicForm): self._create_field(forms.CharField, name, dalias.name, 3) def clean(self): - super(DomainForm, self).clean() + super(DomainFormGeneral, self).clean() if len(self._errors): raise forms.ValidationError(self._errors) @@ -69,7 +69,7 @@ class DomainForm(forms.ModelForm, DynamicForm): return cleaned_data def save(self, user, commit=True): - d = super(DomainForm, self).save(commit=False) + d = super(DomainFormGeneral, self).save(commit=False) if commit: if self.oldname is not None and d.name != self.oldname: if not d.rename_dir(self.oldname): @@ -98,6 +98,32 @@ class DomainForm(forms.ModelForm, DynamicForm): dalias.delete() return d +class DomainForm(TabForms): + def __init__(self, user, *args, **kwargs): + self.user = user + self.forms = [ + dict(id="general", title=_("General"), formtpl="admin/domain_general_form.html", + cls=DomainFormGeneral, mandatory=True), + ] + cbargs = [user] + if kwargs.has_key("instances"): + cbargs += [kwargs["instances"]["general"]] + self.forms += events.raiseQueryEvent("ExtraDomainForm", *cbargs) + + super(DomainForm, self).__init__(*args, **kwargs) + + def save(self, user): + """Custom save method + + As forms interact with each other, it is simpler to make + custom code to save them. + """ + self.forms[0]["instance"].save(user) + if len(self.forms) <= 1: + return + for f in self.forms[1:]: + f["instance"].save() + class DlistForm(forms.ModelForm, DynamicForm): email = forms.EmailField( label=ugettext_lazy("Email address"), diff --git a/admin/views.py b/admin/views.py index a5c98e828..a598cbb8f 100644 --- a/admin/views.py +++ b/admin/views.py @@ -45,7 +45,7 @@ def domains_list(request): return ajax_simple_response(doms) def _validate_domain(request, form, successmsg, commonctx, tplname, - callback=None): + callback=None, tpl_form_name="form"): """Domain form validation Common function shared between creation and modification actions. @@ -56,15 +56,15 @@ def _validate_domain(request, form, successmsg, commonctx, tplname, domain = form.save(request.user) except AdminError, e: error = str(e) - except IntegrityError: - error = _("An alias with this name already exists") + # except IntegrityError: + # error = _("An alias with this name already exists") else: if callback is not None: callback(request.user, domain) messages.info(request, successmsg, fail_silently=True) return ajax_response(request, url=reverse(admin.views.domains)) - commonctx["form"] = form + commonctx[tpl_form_name] = form commonctx["error"] = error return ajax_response(request, status="ko", template=tplname, **commonctx) @@ -83,10 +83,10 @@ def newdomain(request, tplname="admin/newdomainform.html"): "action" : reverse(newdomain), "formid" : "domform"} if request.method == "POST": - form = DomainForm(request.POST) + form = DomainFormGeneral(request.POST) return _validate_domain(request, form, _("Domain created"), commonctx, tplname, callback=newdomain_cb) - form = DomainForm() + form = DomainFormGeneral() commonctx["form"] = form return _render(request, tplname, commonctx) @@ -103,7 +103,10 @@ def editdomain(request, dom_id, tplname="admin/editdomainform.html"): ) if not request.user.is_superuser: domadmins = filter(lambda u: u.group == "DomainAdmins", domadmins) - + + instances = dict(general=domain) + events.raiseEvent("FillDomainInstances", request.user, domain, instances) + commonctx = {"title" : domain.name, "action_label" : _("Update"), "action_classes" : "submit", @@ -111,11 +114,11 @@ def editdomain(request, dom_id, tplname="admin/editdomainform.html"): "formid" : "domform", "domain" : domain} if request.method == "POST": - form = DomainForm(request.POST, instance=domain) - return _validate_domain(request, form, _("Domain modified"), commonctx, tplname) + form = DomainForm(request.user, request.POST, instances=instances) + return _validate_domain(request, form, _("Domain modified"), commonctx, tplname, + tpl_form_name="tabs") - form = DomainForm(instance=domain) - commonctx["form"] = form + commonctx["tabs"] = DomainForm(request.user, instances=instances) commonctx["domadmins"] = domadmins return _render(request, tplname, commonctx) diff --git a/extensions/amavis_quarantine/__init__.py b/extensions/amavis_quarantine/__init__.py index 922e09e13..4774ff1ec 100644 --- a/extensions/amavis_quarantine/__init__.py +++ b/extensions/amavis_quarantine/__init__.py @@ -92,6 +92,17 @@ def menu(target, user): ] return [] +@events.observe("DeleteDomain") +def on_delete_domain(domain): + from models import Users + + try: + u = Users.objects.get(email="@%s" % domain.name) + except Users.DoesNotExist: + return + u.policy.delete() + u.delete() + @events.observe("CreateMailbox") def create_user_record(user, mailbox): from models import Users @@ -170,3 +181,21 @@ def display_requests(user): return [tpl.render(Context(dict( label=_("%d pending requests" % nbrequests), url=url, css=css )))] + +@events.observe("ExtraDomainForm") +def extra_domain_form(user, domain): + from forms import DomainPolicyForm + + if not user.is_superuser and not user.belongs_to_group("Resellers"): + return [] + return [ + dict( + id="amavis", title=_("Amavis"), cls=DomainPolicyForm + ) + ] + +@events.observe("FillDomainInstances") +def fill_domain_instances(user, domain, instances): + if not user.is_superuser and not user.belongs_to_group("Resellers"): + return + instances["amavis"] = domain diff --git a/extensions/amavis_quarantine/forms.py b/extensions/amavis_quarantine/forms.py new file mode 100644 index 000000000..968c47453 --- /dev/null +++ b/extensions/amavis_quarantine/forms.py @@ -0,0 +1,46 @@ +# coding: utf-8 + +from django import forms +from models import Policy, Users + +class DomainPolicyForm(forms.ModelForm): + + class Meta: + model = Policy + fields = ('bypass_virus_checks', 'bypass_spam_checks', 'spam_modifies_subj', + 'spam_tag2_level', 'spam_kill_level') + widgets = { + 'bypass_spam_checks' : forms.Select(attrs={'class' : 'span1'}), + 'bypass_virus_checks' : forms.Select(attrs={'class' : 'span1'}), + 'spam_modifies_subj' : forms.Select(attrs={'class' : 'span1'}), + 'spam_tag2_level' : forms.TextInput(attrs={'class' : 'span1'}), + 'spam_kill_level' : forms.TextInput(attrs={'class' : 'span1'}), + } + + def __init__(self, *args, **kwargs): + if kwargs.has_key("instance"): + self.domain = kwargs["instance"] + try: + policy = Users.objects.get(email="@%s" % self.domain.name).policy + kwargs["instance"] = policy + except (Users.DoesNotExist, Policy.DoesNotExist), e: + del kwargs["instance"] + super(DomainPolicyForm, self).__init__(*args, **kwargs) + + def save(self, commit=True): + p = super(DomainPolicyForm, self).save(commit=False) + if commit: + p.save() + print p.id + 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() + return p diff --git a/extensions/amavis_quarantine/models.py b/extensions/amavis_quarantine/models.py index 10187e656..20f746e2d 100644 --- a/extensions/amavis_quarantine/models.py +++ b/extensions/amavis_quarantine/models.py @@ -10,6 +10,7 @@ # Original Amavis version : 2.6.2 from django.db import models +from django.utils.translation import ugettext as _, ugettext_lazy class Maddr(models.Model): partition_tag = models.IntegerField(unique=True, null=True, blank=True) @@ -68,17 +69,26 @@ class Msgrcpt(models.Model): unique_together = ("mail", "rid") class Policy(models.Model): - id = models.IntegerField(primary_key=True) + 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_virus_checks = models.CharField( + ugettext_lazy("Bypass virus checks"), max_length=3, + choices=(('Y', 'yes'), ('N', 'no')), blank=True + ) + bypass_spam_checks = models.CharField( + ugettext_lazy("Bypass spam checks"), max_length=3, + choices=(('Y', 'yes'), ('N', 'no')), blank=True + ) bypass_banned_checks = models.CharField(max_length=3, blank=True) 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("Modify spam subject"), + choices=(('Y', 'yes'), ('N', 'no')), max_length=3, blank=True + ) 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) @@ -86,8 +96,12 @@ class Policy(models.Model): clean_quarantine_to = models.CharField(max_length=192, blank=True) other_quarantine_to = models.CharField(max_length=192, blank=True) spam_tag_level = models.FloatField(null=True, blank=True) - spam_tag2_level = models.FloatField(null=True, blank=True) - spam_kill_level = models.FloatField(null=True, blank=True) + spam_tag2_level = models.FloatField( + ugettext_lazy("Spam tag2 level"), null=True, blank=True + ) + spam_kill_level = models.FloatField( + ugettext_lazy("Spam kill level"), null=True, blank=True + ) spam_dsn_cutoff_level = models.FloatField(null=True, blank=True) spam_quarantine_cutoff_level = models.FloatField(null=True, blank=True) addr_extension_virus = models.CharField(max_length=192, blank=True) @@ -122,9 +136,9 @@ class Quarantine(models.Model): unique_together = ("mail", "chunk_ind") class Users(models.Model): - id = models.IntegerField(primary_key=True) + id = models.AutoField(primary_key=True) priority = models.IntegerField() - policy_id = models.IntegerField() + policy = models.ForeignKey(Policy) email = models.CharField(unique=True, max_length=255) fullname = models.CharField(max_length=765, blank=True) local = models.CharField(max_length=3, blank=True) diff --git a/lib/events.py b/lib/events.py index 1c282b8ac..f952b2826 100644 --- a/lib/events.py +++ b/lib/events.py @@ -42,6 +42,9 @@ events = [ "ExtraAccountForm", "CheckExtraAccountForm", "FillAccountInstances", + + "ExtraDomainForm", + "FillDomainInstances", "GetExtraRoles", diff --git a/lib/tables.py b/lib/tables.py index 2e19a11b3..07118aab7 100644 --- a/lib/tables.py +++ b/lib/tables.py @@ -28,14 +28,10 @@ class Column: def __unicode__(self): try: label = getattr(self, "label") - except KeyError: + except AttributeError: label = getattr(self, "name") return _(label) - def __str__(self): - return self.__unicode__() - - class SelectionColumn(Column): """Specific column: selection diff --git a/templates/admin/domain_general_form.html b/templates/admin/domain_general_form.html new file mode 100644 index 000000000..168ea9409 --- /dev/null +++ b/templates/admin/domain_general_form.html @@ -0,0 +1,5 @@ +{% load libextras %} +{% render_field form.name %} +{% render_field form.quota %} +{% render_fields_group form "aliases" %} +{% render_field form.enabled %} diff --git a/templates/admin/editdomainform.html b/templates/admin/editdomainform.html index 5f3079be1..e2987715d 100644 --- a/templates/admin/editdomainform.html +++ b/templates/admin/editdomainform.html @@ -1,34 +1,22 @@ -{% extends "common/generic_modal.html" %}{% load i18n libextras admin_extras %} -{% block modalbody %} - -
-
- {% if error %}
{{ error }}
{% endif %} -
- {% render_field form.name %} - {% render_field form.quota %} - {% render_fields_group form "aliases" %} - {% render_field form.enabled %} -
-
-
{% if domadmins %} - - - {% for da in domadmins %} - - {% endfor %} -
{% trans "Username" %}{% trans "Name" %}
{{ da.username }}{{ da.fullname }}{% domadmin_actions da.id domain.id %}
{% else %}
{% trans "No domain administrator defined" %}
{% endif %} -
-
-
{% trans "Creation date" %}{{ domain.creation }}
-
{% trans "Last modification date" %}{{ domain.last_modification }}
-
{% trans "Domain aliases" %}{{ domain.domainalias_count }}
-
{% trans "Mailboxes" %}{{ domain.mailbox_count }}
-
{% trans "Mailbox aliases" %}{{ domain.mbalias_count }}
-
+{% endblock %} +{% block extratabs_content %} +
{% if domadmins %} + + + {% for da in domadmins %} + + {% endfor %} +
{% trans "Username" %}{% trans "Name" %}
{{ da.username }}{{ da.fullname }}{% domadmin_actions da.id domain.id %}
{% else %}
{% trans "No domain administrator defined" %}
{% endif %} +
+
+
{% trans "Creation date" %}{{ domain.creation }}
+
{% trans "Last modification date" %}{{ domain.last_modification }}
+
{% trans "Domain aliases" %}{{ domain.domainalias_count }}
+
{% trans "Mailboxes" %}{{ domain.mailbox_count }}
+
{% trans "Mailbox aliases" %}{{ domain.mbalias_count }}
{% endblock %} diff --git a/templates/common/tabforms.html b/templates/common/tabforms.html index 5d7838b45..bf8ba37e7 100644 --- a/templates/common/tabforms.html +++ b/templates/common/tabforms.html @@ -2,23 +2,21 @@ {% load i18n libextras %} {% block modalbody %}
-