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 %}
-
-
-
{% if domadmins %}
-
- | {% trans "Username" %} | {% trans "Name" %} | |
- {% for da in domadmins %}
- | {{ da.username }} | {{ da.fullname }} | {% domadmin_actions da.id domain.id %} |
-
{% endfor %}
-
{% 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 %}
+
+ | {% trans "Username" %} | {% trans "Name" %} | |
+ {% for da in domadmins %}
+ | {{ da.username }} | {{ da.fullname }} | {% domadmin_actions da.id domain.id %} |
+
{% endfor %}
+
{% 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 %}
{% endblock %}