mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Merge pull request #1034 from modoboa/feature/domain_quota
Domain quota support
This commit is contained in:
@@ -71,6 +71,15 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
)
|
||||
)
|
||||
|
||||
default_mailbox_quota = forms.IntegerField(
|
||||
label=ugettext_lazy("Default mailbox quota"),
|
||||
initial=0,
|
||||
help_text=ugettext_lazy(
|
||||
"Default mailbox quota (in MB) applied to freshly created domains "
|
||||
"with no value specified. A value of 0 means no quota."
|
||||
)
|
||||
)
|
||||
|
||||
auto_account_removal = YesNoField(
|
||||
label=ugettext_lazy("Automatic account removal"),
|
||||
initial=False,
|
||||
@@ -96,7 +105,8 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AdminParametersForm, self).__init__(*args, **kwargs)
|
||||
self.field_widths = {
|
||||
"default_domain_quota": 2
|
||||
"default_domain_quota": 2,
|
||||
"default_mailbox_quota": 2
|
||||
}
|
||||
hide_fields = False
|
||||
dpath = None
|
||||
@@ -127,11 +137,19 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
|
||||
def clean_default_domain_quota(self):
|
||||
"""Ensure quota is a positive integer."""
|
||||
if self.cleaned_data['default_domain_quota'] < 0:
|
||||
if self.cleaned_data["default_domain_quota"] < 0:
|
||||
raise forms.ValidationError(
|
||||
ugettext_lazy('Must be a positive integer')
|
||||
ugettext_lazy("Must be a positive integer")
|
||||
)
|
||||
return self.cleaned_data['default_domain_quota']
|
||||
return self.cleaned_data["default_domain_quota"]
|
||||
|
||||
def clean_default_mailbox_quota(self):
|
||||
"""Ensure quota is a positive integer."""
|
||||
if self.cleaned_data["default_mailbox_quota"] < 0:
|
||||
raise forms.ValidationError(
|
||||
ugettext_lazy("Must be a positive integer")
|
||||
)
|
||||
return self.cleaned_data["default_mailbox_quota"]
|
||||
|
||||
|
||||
def load_admin_settings():
|
||||
|
||||
@@ -16,7 +16,8 @@ class DomainFactory(PermissionFactory):
|
||||
django_get_or_create = ("name", )
|
||||
|
||||
type = "domain"
|
||||
quota = 10
|
||||
quota = 0
|
||||
default_mailbox_quota = 10
|
||||
enabled = True
|
||||
|
||||
|
||||
@@ -64,7 +65,7 @@ def populate_database():
|
||||
|
||||
2 domains, 1 domain admin, 2 users
|
||||
"""
|
||||
dom = DomainFactory(name="test.com")
|
||||
dom = DomainFactory(name="test.com", quota=50)
|
||||
admin = UserFactory(
|
||||
username="admin@test.com", groups=('DomainAdmins', ),
|
||||
password='{PLAIN}toto'
|
||||
@@ -96,7 +97,7 @@ def populate_database():
|
||||
|
||||
dom.add_admin(admin)
|
||||
|
||||
dom2 = DomainFactory.create(name='test2.com', quota=0)
|
||||
dom2 = DomainFactory.create(name='test2.com', default_mailbox_quota=0)
|
||||
admin = UserFactory.create(
|
||||
username='admin@test2.com', groups=('DomainAdmins',),
|
||||
password='{PLAIN}toto'
|
||||
|
||||
@@ -187,7 +187,6 @@ class AccountFormGeneral(forms.ModelForm):
|
||||
|
||||
|
||||
class AccountFormMail(forms.Form, DynamicForm):
|
||||
|
||||
"""Form to handle mail part."""
|
||||
|
||||
email = lib_fields.UTF8EmailField(
|
||||
@@ -280,8 +279,9 @@ class AccountFormMail(forms.Form, DynamicForm):
|
||||
Check if quota is >= 0 only when the domain value is not used.
|
||||
"""
|
||||
cleaned_data = super(AccountFormMail, self).clean()
|
||||
use_default_domain_quota = cleaned_data["quota_act"]
|
||||
condition = (
|
||||
not cleaned_data["quota_act"] and
|
||||
not use_default_domain_quota and
|
||||
cleaned_data["quota"] is not None and
|
||||
cleaned_data["quota"] < 0)
|
||||
if condition:
|
||||
|
||||
@@ -33,14 +33,6 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
type = forms.ChoiceField(
|
||||
label=ugettext_lazy("Type"),
|
||||
)
|
||||
quota = forms.IntegerField(
|
||||
label=ugettext_lazy("Quota"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
"Default quota in MB applied to mailboxes. Leave empty to use the "
|
||||
"default value."
|
||||
)
|
||||
)
|
||||
aliases = DomainNameField(
|
||||
label=ugettext_lazy("Alias(es)"),
|
||||
required=False,
|
||||
@@ -53,14 +45,18 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
class Meta:
|
||||
model = Domain
|
||||
fields = (
|
||||
"name", "type", "quota", "aliases", "enabled", "enable_dns_checks")
|
||||
"name", "type", "quota", "default_mailbox_quota", "aliases",
|
||||
"enabled", "enable_dns_checks")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.oldname = None
|
||||
if "instance" in kwargs:
|
||||
self.oldname = kwargs["instance"].name
|
||||
super(DomainFormGeneral, self).__init__(*args, **kwargs)
|
||||
|
||||
params = dict(param_tools.get_global_parameters("admin"))
|
||||
self.fields["quota"].initial = params["default_domain_quota"]
|
||||
self.fields["default_mailbox_quota"].initial = (
|
||||
params["default_mailbox_quota"])
|
||||
extra_domain_types = reduce(
|
||||
lambda a, b: a + b,
|
||||
[result[1] for result in signals.extra_domain_types.send(
|
||||
@@ -68,7 +64,8 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
)
|
||||
self.fields["type"].choices = DOMAIN_TYPES + extra_domain_types
|
||||
self.field_widths = {
|
||||
"quota": 3
|
||||
"quota": 3,
|
||||
"default_mailbox_quota": 3
|
||||
}
|
||||
|
||||
if len(args) and isinstance(args[0], QueryDict):
|
||||
@@ -79,14 +76,6 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
name = "aliases_%d" % (pos + 1)
|
||||
self._create_field(forms.CharField, name, dalias.name, 3)
|
||||
|
||||
def clean_quota(self):
|
||||
"""Check quota value."""
|
||||
if self.cleaned_data["quota"] is None:
|
||||
return param_tools.get_global_parameter("default_domain_quota")
|
||||
if self.cleaned_data["quota"] < 0:
|
||||
raise forms.ValidationError(_("Must be a positive integer"))
|
||||
return self.cleaned_data["quota"]
|
||||
|
||||
def clean(self):
|
||||
"""Custom fields validation.
|
||||
|
||||
@@ -164,7 +153,6 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
|
||||
|
||||
class DomainFormOptions(forms.Form):
|
||||
|
||||
"""A form containing options for domain creation."""
|
||||
|
||||
create_dom_admin = YesNoField(
|
||||
@@ -271,7 +259,6 @@ class DomainFormOptions(forms.Form):
|
||||
|
||||
|
||||
class DomainForm(TabForms):
|
||||
|
||||
"""Domain edition form."""
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
@@ -341,7 +328,6 @@ class DomainForm(TabForms):
|
||||
|
||||
|
||||
class DomainWizard(WizardForm):
|
||||
|
||||
"""Domain creation wizard."""
|
||||
|
||||
def __init__(self, request):
|
||||
|
||||
@@ -27,7 +27,7 @@ def update_domain_mxs_and_mailboxes(sender, instance, **kwargs):
|
||||
if kwargs.get("created"):
|
||||
return
|
||||
instance.mailbox_set.filter(use_domain_quota=True).update(
|
||||
quota=instance.quota)
|
||||
quota=instance.default_mailbox_quota)
|
||||
if instance.old_mail_homes is None:
|
||||
return
|
||||
qset = (
|
||||
@@ -155,7 +155,8 @@ def account_auto_created(sender, user, **kwargs):
|
||||
domname, [(models.DomainAlias, _("domain alias"))])
|
||||
if label is not None:
|
||||
return
|
||||
domain = models.Domain(name=domname, enabled=True, quota=0)
|
||||
domain = models.Domain(
|
||||
name=domname, enabled=True, default_mailbox_quota=0)
|
||||
domain.save(creator=sadmins[0])
|
||||
for su in sadmins[1:]:
|
||||
permissions.grant_access_to_object(su, domain)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-02-15 08:48
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('admin', '0008_domain_enable_dns_checks'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='domain',
|
||||
old_name='quota',
|
||||
new_name='default_mailbox_quota',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-02-15 12:28
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('admin', '0009_auto_20170215_0948'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='domain',
|
||||
name='quota',
|
||||
field=models.PositiveIntegerField(default=0, help_text='Quota in MB shared between mailboxes. A value of 0 means no quota.'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='domain',
|
||||
name='default_mailbox_quota',
|
||||
field=models.PositiveIntegerField(default=0, help_text='Default quota in MB applied to mailboxes. A value of 0 means no quota.', verbose_name='Default mailbox quota'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='mailbox',
|
||||
name='quota',
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
]
|
||||
@@ -42,7 +42,21 @@ class Domain(AdminObject):
|
||||
|
||||
name = models.CharField(ugettext_lazy('name'), max_length=100, unique=True,
|
||||
help_text=ugettext_lazy("The domain name"))
|
||||
quota = models.IntegerField()
|
||||
quota = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text=ugettext_lazy(
|
||||
"Quota in MB shared between mailboxes. A value of 0 means "
|
||||
"no quota."
|
||||
)
|
||||
)
|
||||
default_mailbox_quota = models.PositiveIntegerField(
|
||||
verbose_name=ugettext_lazy("Default mailbox quota"),
|
||||
default=0,
|
||||
help_text=ugettext_lazy(
|
||||
"Default quota in MB applied to mailboxes. A value of 0 means "
|
||||
"no quota."
|
||||
)
|
||||
)
|
||||
enabled = models.BooleanField(
|
||||
ugettext_lazy('enabled'),
|
||||
help_text=ugettext_lazy("Check to activate this domain"),
|
||||
@@ -143,6 +157,23 @@ class Domain(AdminObject):
|
||||
else:
|
||||
return "success"
|
||||
|
||||
@cached_property
|
||||
def quota_usage(self):
|
||||
"""Return current quota usage."""
|
||||
if not self.quota:
|
||||
return 0
|
||||
if not self.mailbox_set.exists():
|
||||
return 0
|
||||
return self.mailbox_set.aggregate(
|
||||
total=models.Sum("quota"))["total"]
|
||||
|
||||
@cached_property
|
||||
def quota_usage_in_percent(self):
|
||||
"""Return quota usage in percent."""
|
||||
if not self.quota_usage:
|
||||
return 0
|
||||
return int(self.quota_usage / float(self.quota) * 100)
|
||||
|
||||
def add_admin(self, account):
|
||||
"""Add a new administrator to this domain.
|
||||
|
||||
@@ -210,12 +241,12 @@ class Domain(AdminObject):
|
||||
|
||||
The expected fields order is the following::
|
||||
|
||||
"domain", name, quota, enabled
|
||||
"domain", name, quota, default_mailbox_quota, enabled
|
||||
|
||||
:param ``core.User`` user: user creating the domain
|
||||
:param str row: a list containing domain's definition
|
||||
"""
|
||||
if len(row) < 4:
|
||||
if len(row) < 5:
|
||||
raise BadRequest(_("Invalid line"))
|
||||
self.name = row[1].strip()
|
||||
if Domain.objects.filter(name=self.name).exists():
|
||||
@@ -224,12 +255,25 @@ class Domain(AdminObject):
|
||||
self.quota = int(row[2].strip())
|
||||
except ValueError:
|
||||
raise BadRequest(
|
||||
_("Invalid quota value for domain '%s'") % self.name)
|
||||
self.enabled = (row[3].strip() in ["True", "1", "yes", "y"])
|
||||
_("Invalid quota value for domain '{}'")
|
||||
.format(self.name)
|
||||
)
|
||||
try:
|
||||
self.default_mailbox_quota = int(row[3].strip())
|
||||
except ValueError:
|
||||
raise BadRequest(
|
||||
_("Invalid default mailbox quota value for domain '{}'")
|
||||
.format(self.name)
|
||||
)
|
||||
self.enabled = (row[4].strip() in ["True", "1", "yes", "y"])
|
||||
self.save(creator=user)
|
||||
|
||||
def to_csv(self, csvwriter):
|
||||
csvwriter.writerow(["domain", self.name, self.quota, self.enabled])
|
||||
"""Export domain and domain aliases to CSV format."""
|
||||
csvwriter.writerow([
|
||||
"domain", self.name, self.quota, self.default_mailbox_quota,
|
||||
self.enabled
|
||||
])
|
||||
for dalias in self.domainalias_set.all():
|
||||
dalias.to_csv(csvwriter)
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class Mailbox(AdminObject):
|
||||
help_text=ugettext_lazy(
|
||||
"Mailbox address (without the @domain.tld part)")
|
||||
)
|
||||
quota = models.PositiveIntegerField()
|
||||
quota = models.PositiveIntegerField(default=0)
|
||||
use_domain_quota = models.BooleanField(default=False)
|
||||
domain = models.ForeignKey(Domain)
|
||||
user = models.OneToOneField(User)
|
||||
@@ -218,7 +218,7 @@ class Mailbox(AdminObject):
|
||||
MailboxOperation.objects.create(type="delete", argument=self.mail_home)
|
||||
|
||||
def set_quota(self, value=None, override_rules=False):
|
||||
"""Set or update quota's value for this mailbox.
|
||||
"""Set or update quota value for this mailbox.
|
||||
|
||||
A value equal to 0 means the mailbox won't have any quota. The
|
||||
following cases allow people to define such behaviour:
|
||||
@@ -228,20 +228,23 @@ class Mailbox(AdminObject):
|
||||
:param integer value: the quota's value
|
||||
:param bool override_rules: allow to override defined quota rules
|
||||
"""
|
||||
old_quota = self.quota
|
||||
if value is None:
|
||||
if self.use_domain_quota:
|
||||
self.quota = self.domain.quota
|
||||
self.quota = self.domain.default_mailbox_quota
|
||||
else:
|
||||
self.quota = 0
|
||||
elif int(value) > self.domain.quota and not override_rules:
|
||||
raise lib_exceptions.BadRequest(
|
||||
_("Quota is greater than the allowed domain's limit (%dM)") %
|
||||
self.domain.quota
|
||||
)
|
||||
else:
|
||||
self.quota = value
|
||||
if not self.quota and self.domain.quota and not override_rules:
|
||||
raise lib_exceptions.BadRequest(_("A quota is required"))
|
||||
if self.quota == 0:
|
||||
if self.domain.quota and not override_rules:
|
||||
raise lib_exceptions.BadRequest(_("A quota is required"))
|
||||
elif self.domain.quota:
|
||||
quota_usage = self.domain.quota_usage
|
||||
if old_quota:
|
||||
quota_usage -= old_quota
|
||||
if quota_usage + self.quota > self.domain.quota:
|
||||
raise lib_exceptions.BadRequest(_("Domain quota exceeded"))
|
||||
|
||||
def get_quota(self):
|
||||
"""Get quota limit.
|
||||
|
||||
@@ -23,7 +23,9 @@ class DomainSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = models.Domain
|
||||
fields = ("pk", "name", "quota", "enabled", "type", )
|
||||
fields = (
|
||||
"pk", "name", "quota", "default_mailbox_quota", "enabled", "type",
|
||||
)
|
||||
|
||||
def create(self, validated_data):
|
||||
"""Set permissions."""
|
||||
@@ -236,11 +238,10 @@ class WritableAccountSerializer(AccountSerializer):
|
||||
except lib_exceptions.ModoboaException as inst:
|
||||
raise serializers.ValidationError({
|
||||
"domain": unicode(inst)})
|
||||
quota = data.pop("quota", None)
|
||||
mb = admin_models.Mailbox(
|
||||
user=account, address=address, domain=domain, **data)
|
||||
mb.set_quota(
|
||||
data.get("quota"), creator.has_perm("admin.add_domain")
|
||||
)
|
||||
mb.set_quota(quota, creator.has_perm("admin.add_domain"))
|
||||
mb.save(creator=creator)
|
||||
account.email = full_address
|
||||
return mb
|
||||
|
||||
@@ -20,21 +20,50 @@
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Summary" %}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
{% if enable_mx_checks or enable_dnsbl_checks %}
|
||||
<div class="row">
|
||||
<span class="title">{% trans "DNS status" %}</span>
|
||||
{% include "admin/_domain_dnschecks_status.html" %}
|
||||
</div>
|
||||
<tr>
|
||||
<th>{% trans "DNS status" %}</th>
|
||||
<td>
|
||||
{% include "admin/_domain_dnschecks_status.html" %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<span class="title">{% trans "Creation date" %}</span><span>{{ domain.creation }}</span>
|
||||
</div>
|
||||
<div class="row"><span class="title">{% trans "Last modification date" %}</span><span>{{ domain.last_modification }}</span></div>
|
||||
<div class="row"><span class="title">{% trans "Domain aliases" %}</span><span>{{ domain.domainalias_count }}</span></div>
|
||||
<div class="row"><span class="title"><a href="{% url 'admin:identity_list' %}#list/?searchquery=@{{ object.name }}">{% trans "Mailboxes" %}</a></span><span>{{ domain.mailbox_count }}</span></div>
|
||||
<div class="row"><span class="title"><a href="{% url 'admin:identity_list' %}#list/?searchquery=@{{ object.name }}">{% trans "Mailbox aliases" %}</a></span><span>{{ domain.mbalias_count }}</span></div>
|
||||
</div>
|
||||
<tr>
|
||||
<th width="40%">{% trans "Creation date" %}</th>
|
||||
<td>{{ domain.creation }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Last modification date" %}</th>
|
||||
<td>{{ domain.last_modification }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Domain aliases" %}</th>
|
||||
<td>{{ domain.domainalias_count }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a href="{% url 'admin:identity_list' %}#list/?searchquery=@{{ object.name }}">{% trans "Mailboxes" %}</a></th>
|
||||
<td>{{ domain.mailbox_count }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><a href="{% url 'admin:identity_list' %}#list/?searchquery=@{{ object.name }}">{% trans "Mailbox aliases" %}</a></th>
|
||||
<td>{{ domain.mbalias_count }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Quota" %}</a></th>
|
||||
<td>{{ domain.quota }} {% trans "MB" %}</td>
|
||||
</tr>
|
||||
{% if domain.quota %}
|
||||
<tr>
|
||||
<th>{% trans "Usage" %}</a></th>
|
||||
<td>{% include "common/progressbar.html" with id="quotabar" value=domain.quota_usage_in_percent %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th>{% trans "Default mailbox quota" %}</a></th>
|
||||
<td>{{ domain.default_mailbox_quota }} {% trans "MB" %}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if object.domainalias_set.exists %}
|
||||
@@ -58,24 +87,26 @@
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">{% trans "Administrators" %}</h3></div>
|
||||
<div class="panel-body">
|
||||
<table id="domadmins" class="table table-condensed">
|
||||
<table id="domadmins" class="table">
|
||||
<thead>
|
||||
<tr><th>{% trans "Username" %}</th><th>{% trans "Name" %}</th><th></th></tr>
|
||||
{% for da in domain.admins %}
|
||||
<tr>
|
||||
<td>{{ da.username }}</td>
|
||||
<td>{{ da.fullname }}</td>
|
||||
<td name="actions">
|
||||
{% if perms.admin.change_domain %}
|
||||
<a name="removeperm" href="{% url 'admin:permission_remove' %}?domid={{ domain.id }}&daid={{ da.id }}" title="{% trans 'Remove this permission' %}"><span class="fa fa-trash"></span></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="3">{% trans "No domain administrator defined yet." %}</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for da in domain.admins %}
|
||||
<tr>
|
||||
<td>{{ da.username }}</td>
|
||||
<td>{{ da.fullname }}</td>
|
||||
<td name="actions">
|
||||
{% if perms.admin.change_domain %}
|
||||
<a name="removeperm" href="{% url 'admin:permission_remove' %}?domid={{ domain.id }}&daid={{ da.id }}" title="{% trans 'Remove this permission' %}"><span class="fa fa-trash"></span></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="3">{% trans "No domain administrator defined yet." %}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% for template in templates.right %}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{% render_field form.name %}
|
||||
{% render_field form.type %}
|
||||
{% render_field form.quota appended_text=_("MB") %}
|
||||
{% render_field form.default_mailbox_quota appended_text=_("MB") %}
|
||||
{% render_fields_group form "aliases" %}
|
||||
{% render_field form.enabled %}
|
||||
{% render_field form.enable_dns_checks %}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
{% blocktrans trimmed %}
|
||||
Provide a CSV file where lines respect one of the following formats:
|
||||
<ul>
|
||||
<li><em>domain; name; quota; enabled</em></li>
|
||||
<li><em>domain; name; quota; default mailbox quota; enabled</em></li>
|
||||
<li><em>domainalias; name; targeted domain; enabled</em></li>
|
||||
<li><em>relaydomain; name; target host; target port; service; enabled; verify recipients</em></li>
|
||||
</ul>
|
||||
|
||||
@@ -165,17 +165,34 @@ class AccountTestCase(ModoTestCase):
|
||||
self._set_quota("user@test.com", 0)
|
||||
|
||||
def test_set_nul_quota_as_domainadmin(self):
|
||||
"""Check cases where a domain admin set unlimited quota."""
|
||||
self.client.logout()
|
||||
self.assertTrue(
|
||||
self.client.login(username="admin@test.com", password="toto")
|
||||
)
|
||||
# Fails because domain has a quota
|
||||
self._set_quota("user@test.com", 0, 400)
|
||||
self.client.logout()
|
||||
self.assertTrue(
|
||||
self.client.login(username="admin@test2.com", password="toto")
|
||||
)
|
||||
# Ok because domain has no quota
|
||||
self._set_quota("user@test2.com", 0)
|
||||
|
||||
def test_domain_quota(self):
|
||||
"""Check domain quota."""
|
||||
dom = models.Domain.objects.get(name="test.com")
|
||||
dom.quota = 100
|
||||
dom.save(update_fields=["quota"])
|
||||
# 2 x 10MB
|
||||
self.assertEqual(dom.quota_usage, 20)
|
||||
self._set_quota("user@test.com", 80)
|
||||
del dom.quota_usage
|
||||
# 10 + 80 < 100 => ok
|
||||
self.assertEqual(dom.quota_usage, 90)
|
||||
# 30 + 80 > 100 => failure
|
||||
self._set_quota("admin@test.com", 30, 400)
|
||||
|
||||
def test_master_user(self):
|
||||
"""Validate the master user mode."""
|
||||
values = {
|
||||
@@ -250,11 +267,15 @@ class PermissionsTestCase(ModoTestCase):
|
||||
cls.reseller = core_factories.UserFactory(username="reseller")
|
||||
cls.reseller.role = "Resellers"
|
||||
cls.user = User.objects.get(username="user@test.com")
|
||||
cls.values = dict(
|
||||
username=cls.user.username, role="DomainAdmins",
|
||||
is_active=cls.user.is_active, email="user@test.com",
|
||||
quota_act=True
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
"""Initiate test context."""
|
||||
super(PermissionsTestCase, self).setUp()
|
||||
self.values = {
|
||||
"username": self.user.username, "role": "DomainAdmins",
|
||||
"is_active": self.user.is_active, "email": "user@test.com",
|
||||
"quota_act": True
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
self.client.logout()
|
||||
|
||||
@@ -43,18 +43,20 @@ class DomainAPITestCase(ModoAPITestCase):
|
||||
def test_create_domain(self):
|
||||
"""Check domain creation."""
|
||||
url = reverse("external_api:domain-list")
|
||||
response = self.client.post(url, {"name": "test3.com", "quota": 10})
|
||||
response = self.client.post(
|
||||
url, {"name": "test3.com", "quota": 0, "default_mailbox_quota": 10}
|
||||
)
|
||||
self.assertEqual(response.status_code, 201)
|
||||
self.assertTrue(
|
||||
models.Domain.objects.filter(name="test3.com").exists())
|
||||
response = self.client.post(url, {})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn("name", response.data)
|
||||
self.assertIn("quota", response.data)
|
||||
|
||||
self.client.credentials(
|
||||
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
|
||||
response = self.client.post(url, {"name": "test4.com", "quota": 10})
|
||||
response = self.client.post(
|
||||
url, {"name": "test4.com", "default_mailbox_quota": 10})
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_update_domain(self):
|
||||
@@ -64,15 +66,17 @@ class DomainAPITestCase(ModoAPITestCase):
|
||||
domain__name="test.com", address="user").update(
|
||||
use_domain_quota=True)
|
||||
url = reverse("external_api:domain-detail", args=[domain.pk])
|
||||
response = self.client.put(url, {"name": "test.com", "quota": 1000})
|
||||
response = self.client.put(
|
||||
url, {"name": "test.com", "default_mailbox_quota": 1000})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
domain.refresh_from_db()
|
||||
self.assertEqual(domain.quota, 1000)
|
||||
self.assertEqual(domain.default_mailbox_quota, 1000)
|
||||
mb = models.Mailbox.objects.get(
|
||||
domain__name="test.com", address="user")
|
||||
self.assertEqual(mb.quota, 1000)
|
||||
|
||||
response = self.client.put(url, {"name": "test42.com", "quota": 1000})
|
||||
response = self.client.put(
|
||||
url, {"name": "test42.com", "default_mailbox_quota": 1000})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue(
|
||||
models.Mailbox.objects.filter(
|
||||
@@ -267,7 +271,8 @@ class AccountAPITestCase(ModoAPITestCase):
|
||||
user = core_models.User.objects.filter(pk=account["pk"]).first()
|
||||
self.assertIsNot(user, None)
|
||||
self.assertIsNot(user.mailbox, None)
|
||||
self.assertEqual(user.mailbox.quota, user.mailbox.domain.quota)
|
||||
self.assertEqual(
|
||||
user.mailbox.quota, user.mailbox.domain.default_mailbox_quota)
|
||||
|
||||
def test_create_existing_account(self):
|
||||
"""Check if unicity is respected."""
|
||||
@@ -297,7 +302,7 @@ class AccountAPITestCase(ModoAPITestCase):
|
||||
self.client.credentials(
|
||||
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
|
||||
data = copy.deepcopy(self.ACCOUNT_DATA)
|
||||
data["mailbox"]["quota"] = 20
|
||||
data["mailbox"]["quota"] = 1000
|
||||
url = reverse("external_api:account-list")
|
||||
response = self.client.post(url, data, format="json")
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
@@ -25,35 +25,37 @@ class DomainTestCase(ModoTestCase):
|
||||
def test_create(self):
|
||||
"""Test the creation of a domain."""
|
||||
values = {
|
||||
"name": "pouet.com", "quota": 100, "create_dom_admin": False,
|
||||
"type": "domain", "stepid": "step3"
|
||||
"name": "pouet.com", "quota": 1000, "default_mailbox_quota": 100,
|
||||
"create_dom_admin": False, "type": "domain", "stepid": "step3"
|
||||
}
|
||||
self.ajax_post(reverse("admin:domain_add"), values)
|
||||
dom = Domain.objects.get(name="pouet.com")
|
||||
self.assertEqual(dom.name, "pouet.com")
|
||||
self.assertEqual(dom.quota, 100)
|
||||
self.assertEqual(dom.quota, 1000)
|
||||
self.assertEqual(dom.default_mailbox_quota, 100)
|
||||
self.assertEqual(dom.enabled, False)
|
||||
self.assertFalse(dom.admins)
|
||||
|
||||
def test_create_utf8(self):
|
||||
"""Test the creation of a domain with non-ASCII characters."""
|
||||
values = {
|
||||
"name": "pouét.com", "quota": 100, "create_dom_admin": False,
|
||||
"type": "domain", "stepid": "step3"
|
||||
"name": "pouét.com", "quota": 1000, "default_mailbox_quota": 100,
|
||||
"create_dom_admin": False, "type": "domain", "stepid": "step3"
|
||||
}
|
||||
self.ajax_post(reverse("admin:domain_add"), values)
|
||||
dom = Domain.objects.get(name=u"pouét.com")
|
||||
self.assertEqual(dom.name, u"pouét.com")
|
||||
self.assertEqual(dom.quota, 100)
|
||||
self.assertEqual(dom.quota, 1000)
|
||||
self.assertEqual(dom.default_mailbox_quota, 100)
|
||||
self.assertEqual(dom.enabled, False)
|
||||
self.assertFalse(dom.admins)
|
||||
|
||||
def test_create_with_template(self):
|
||||
"""Test the creation of a domain with a template."""
|
||||
values = {
|
||||
"name": "pouet.com", "quota": 100, "create_dom_admin": True,
|
||||
"dom_admin_username": "toto", "create_aliases": True,
|
||||
"type": "domain", "stepid": 'step3'
|
||||
"name": "pouet.com", "quota": 1000, "default_mailbox_quota": 100,
|
||||
"create_dom_admin": True, "dom_admin_username": "toto",
|
||||
"create_aliases": True, "type": "domain", "stepid": 'step3'
|
||||
}
|
||||
self.ajax_post(reverse("admin:domain_add"), values)
|
||||
dom = Domain.objects.get(name="pouet.com")
|
||||
@@ -67,9 +69,9 @@ class DomainTestCase(ModoTestCase):
|
||||
self.assertTrue(da.can_access(al))
|
||||
|
||||
values = {
|
||||
"name": "pouet2.com", "quota": 100, "create_dom_admin": True,
|
||||
"dom_admin_username": "postmaster", "create_aliases": True,
|
||||
"type": "domain", "stepid": "step3"
|
||||
"name": "pouet2.com", "quota": 1000, "default_mailbox_quota": 100,
|
||||
"create_dom_admin": True, "dom_admin_username": "postmaster",
|
||||
"create_aliases": True, "type": "domain", "stepid": "step3"
|
||||
}
|
||||
self.ajax_post(reverse("admin:domain_add"), values)
|
||||
self.assertTrue(
|
||||
@@ -81,9 +83,9 @@ class DomainTestCase(ModoTestCase):
|
||||
def test_create_with_template_and_empty_quota(self):
|
||||
"""Test the creation of a domain with a template and no quota"""
|
||||
values = {
|
||||
"name": "pouet.com", "quota": 0, "create_dom_admin": True,
|
||||
"dom_admin_username": "toto", "create_aliases": True,
|
||||
"type": "domain", "stepid": 'step3'
|
||||
"name": "pouet.com", "quota": 0, "default_mailbox_quota": 0,
|
||||
"create_dom_admin": True, "dom_admin_username": "toto",
|
||||
"create_aliases": True, "type": "domain", "stepid": 'step3'
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:domain_add"),
|
||||
@@ -104,9 +106,9 @@ class DomainTestCase(ModoTestCase):
|
||||
password = "Toto1000"
|
||||
self.set_global_parameter("default_password", password, app="core")
|
||||
values = {
|
||||
"name": "pouet.com", "quota": 0, "create_dom_admin": True,
|
||||
"dom_admin_username": "toto", "create_aliases": True,
|
||||
"type": "domain", "stepid": 'step3'
|
||||
"name": "pouet.com", "quota": 0, "default_mailbox_quota": 0,
|
||||
"create_dom_admin": True, "dom_admin_username": "toto",
|
||||
"create_aliases": True, "type": "domain", "stepid": 'step3'
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:domain_add"),
|
||||
@@ -125,20 +127,12 @@ class DomainTestCase(ModoTestCase):
|
||||
self.client.login(username="toto@pouet.com", password=password))
|
||||
|
||||
def test_create_using_default_quota(self):
|
||||
self.set_global_parameter("default_domain_quota", 50)
|
||||
values = {
|
||||
"name": "pouet.com", "create_dom_admin": True,
|
||||
"dom_admin_username": "toto", "create_aliases": True,
|
||||
"type": "domain", "stepid": 'step3'
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:domain_add"),
|
||||
values
|
||||
)
|
||||
dom = Domain.objects.get(name="pouet.com")
|
||||
self.assertEqual(dom.quota, 50)
|
||||
da = User.objects.get(username="toto@pouet.com")
|
||||
self.assertEqual(da.mailbox.quota, 50)
|
||||
"""Check that default value is used for creation."""
|
||||
self.set_global_parameter("default_domain_quota", 500)
|
||||
self.set_global_parameter("default_mailbox_quota", 50)
|
||||
response = self.client.get(reverse("admin:domain_add"))
|
||||
self.assertContains(response, "value=\"500\"")
|
||||
self.assertContains(response, "value=\"50\"")
|
||||
|
||||
def test_modify(self):
|
||||
"""Test the modification of a domain
|
||||
@@ -146,8 +140,8 @@ class DomainTestCase(ModoTestCase):
|
||||
Rename 'test.com' domain to 'pouet.com'
|
||||
"""
|
||||
values = {
|
||||
"name": "pouet.com", "quota": 100, "type": "domain",
|
||||
"enabled": True
|
||||
"name": "pouet.com", "quota": 1000, "default_mailbox_quota": 100,
|
||||
"type": "domain", "enabled": True
|
||||
}
|
||||
dom = Domain.objects.get(name="test.com")
|
||||
self.ajax_post(
|
||||
|
||||
@@ -38,11 +38,12 @@ class DomainAliasTestCase(ModoTestCase):
|
||||
|
||||
def test_form(self):
|
||||
dom = Domain.objects.get(name="test.com")
|
||||
values = dict(
|
||||
name=dom.name, quota=dom.quota, enabled=dom.enabled,
|
||||
aliases="domalias.net", aliases_1="domaliasé.com",
|
||||
type="domain"
|
||||
)
|
||||
values = {
|
||||
"name": dom.name, "quota": dom.quota,
|
||||
"default_mailbox_quota": dom.default_mailbox_quota,
|
||||
"enabled": dom.enabled, "aliases": "domalias.net",
|
||||
"aliases_1": "domaliasé.com", "type": "domain"
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:domain_change",
|
||||
args=[dom.id]),
|
||||
|
||||
@@ -5,10 +5,10 @@ from django.core.urlresolvers import reverse
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
from .. import factories
|
||||
from .. import models
|
||||
|
||||
|
||||
class ExportTestCase(ModoTestCase):
|
||||
|
||||
"""Test case for export operations."""
|
||||
|
||||
@classmethod
|
||||
@@ -17,6 +17,14 @@ class ExportTestCase(ModoTestCase):
|
||||
super(ExportTestCase, cls).setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def __export_domains(self, domfilter=""):
|
||||
self.client.get(
|
||||
"{}?domfilter={}".format(
|
||||
reverse("admin:_domain_list"), domfilter))
|
||||
return self.client.post(
|
||||
reverse("admin:domain_export"), {"filename": "test.csv"}
|
||||
)
|
||||
|
||||
def __export_identities(self, idtfilter="", grpfilter=""):
|
||||
self.client.get(
|
||||
reverse("admin:_identity_list") +
|
||||
@@ -28,12 +36,29 @@ class ExportTestCase(ModoTestCase):
|
||||
)
|
||||
|
||||
def assertListEqual(self, list1, list2):
|
||||
list2 = list2.split('\r\n')
|
||||
for entry in list1.split('\r\n'):
|
||||
list1 = list1.split("\r\n")
|
||||
list2 = list2.split("\r\n")
|
||||
self.assertEqual(len(list1), len(list2))
|
||||
for entry in list1:
|
||||
if not entry:
|
||||
continue
|
||||
self.assertIn(entry, list2)
|
||||
|
||||
def test_export_domains(self):
|
||||
"""Check domain export."""
|
||||
dom = models.Domain.objects.get(name="test.com")
|
||||
factories.DomainAliasFactory(name="alias.test", target=dom)
|
||||
response = self.__export_domains()
|
||||
expected_response = [
|
||||
"domain;test.com;50;10;True",
|
||||
"domainalias;alias.test;test.com;True",
|
||||
"domain;test2.com;0;0;True",
|
||||
]
|
||||
self.assertListEqual(
|
||||
"\r\n".join(expected_response),
|
||||
response.content.strip()
|
||||
)
|
||||
|
||||
def test_export_identities(self):
|
||||
response = self.__export_identities()
|
||||
self.assertListEqual(
|
||||
|
||||
@@ -25,8 +25,8 @@ class ImportTestCase(ModoTestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn("Provide a CSV", response.content)
|
||||
|
||||
f = ContentFile(b"""domain; domain1.com; 100; True
|
||||
domain; domain2.com; 200; False
|
||||
f = ContentFile(b"""domain; domain1.com; 1000; 100; True
|
||||
domain; domain2.com; 1000; 200; False
|
||||
domainalias; domalias1.com; domain1.com; True
|
||||
""", name="domains.csv")
|
||||
self.client.post(
|
||||
@@ -36,7 +36,8 @@ domainalias; domalias1.com; domain1.com; True
|
||||
)
|
||||
admin = User.objects.get(username="admin")
|
||||
dom = Domain.objects.get(name="domain1.com")
|
||||
self.assertEqual(dom.quota, 100)
|
||||
self.assertEqual(dom.quota, 1000)
|
||||
self.assertEqual(dom.default_mailbox_quota, 100)
|
||||
self.assertTrue(dom.enabled)
|
||||
self.assertTrue(admin.is_owner(dom))
|
||||
domalias = DomainAlias.objects.get(name="domalias1.com")
|
||||
@@ -44,12 +45,28 @@ domainalias; domalias1.com; domain1.com; True
|
||||
self.assertTrue(dom.enabled)
|
||||
self.assertTrue(admin.is_owner(domalias))
|
||||
dom = Domain.objects.get(name="domain2.com")
|
||||
self.assertEqual(dom.quota, 200)
|
||||
self.assertEqual(dom.default_mailbox_quota, 200)
|
||||
self.assertFalse(dom.enabled)
|
||||
self.assertTrue(admin.is_owner(dom))
|
||||
|
||||
def test_domain_import_bad_syntax(self):
|
||||
"""Check errors handling."""
|
||||
url = reverse("admin:domain_import")
|
||||
f = ContentFile("domain; domain1.com; 100; True",
|
||||
name="domains.csv")
|
||||
response = self.client.post(url, {"sourcefile": f})
|
||||
self.assertContains(response, "Invalid line")
|
||||
f = ContentFile("domain; domain1.com; XX; 100; True",
|
||||
name="domains.csv")
|
||||
response = self.client.post(url, {"sourcefile": f})
|
||||
self.assertContains(response, "Invalid quota value")
|
||||
f = ContentFile("domain; domain1.com; 100; XX; True",
|
||||
name="domains.csv")
|
||||
response = self.client.post(url, {"sourcefile": f})
|
||||
self.assertContains(response, "Invalid default mailbox quota")
|
||||
|
||||
def test_import_domains_with_conflict(self):
|
||||
f = ContentFile(b"""domain;test.alias;10;True
|
||||
f = ContentFile(b"""domain;test.alias;100;10;True
|
||||
domainalias;test.alias;test.com;True
|
||||
""", name="domains.csv")
|
||||
resp = self.client.post(
|
||||
@@ -160,7 +177,7 @@ account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; ; t
|
||||
self.client.logout()
|
||||
self.client.login(username="admin@test.com", password="toto")
|
||||
f = ContentFile(b"""
|
||||
domain; domain2.com; 200; False
|
||||
domain; domain2.com; 1000; 200; False
|
||||
""", name="identities.csv")
|
||||
resp = self.client.post(
|
||||
reverse("admin:identity_import"),
|
||||
@@ -181,13 +198,13 @@ domainalias; domalias1.com; test.com; True
|
||||
self.client.logout()
|
||||
self.client.login(username="admin@test.com", password="toto")
|
||||
f = ContentFile(b"""
|
||||
account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; 20
|
||||
account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; 40
|
||||
""", name="identities.csv")
|
||||
resp = self.client.post(
|
||||
reverse("admin:identity_import"),
|
||||
{"sourcefile": f, "crypt_password": True}
|
||||
)
|
||||
self.assertIn('Quota is greater than the allowed', resp.content)
|
||||
self.assertIn("Domain quota exceeded", resp.content)
|
||||
|
||||
def test_import_missing_quota(self):
|
||||
f = ContentFile(b"""
|
||||
@@ -200,7 +217,7 @@ account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com
|
||||
account = User.objects.get(username="user1@test.com")
|
||||
self.assertEqual(
|
||||
account.mailbox.quota,
|
||||
account.mailbox.domain.quota
|
||||
account.mailbox.domain.default_mailbox_quota
|
||||
)
|
||||
|
||||
def test_import_duplicate(self):
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-02-15 09:34
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def rename_settings(apps, schema_editor):
|
||||
"""Rename settings."""
|
||||
LocalConfig = apps.get_model("core", "LocalConfig")
|
||||
lc = LocalConfig.objects.first()
|
||||
condition = (
|
||||
lc and
|
||||
"admin" in lc._parameters and
|
||||
"default_domain_quota" in lc._parameters["admin"]
|
||||
)
|
||||
if condition:
|
||||
lc._parameters["admin"]["default_mailbox_quota"] = (
|
||||
lc._parameters["admin"]["default_domain_quota"])
|
||||
del lc._parameters["admin"]["default_domain_quota"]
|
||||
lc.save(update_fields=["_parameters"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0011_auto_20161104_2217'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_settings)
|
||||
]
|
||||
@@ -115,6 +115,7 @@ class SettingsTestCase(ModoTestCase):
|
||||
"admin-auto_create_domain_and_mailbox": "True",
|
||||
"admin-enable_dnsbl_checks": "True",
|
||||
"admin-default_domain_quota": "0",
|
||||
"admin-default_mailbox_quota": "0",
|
||||
"core-ldap_server_address": "localhost",
|
||||
"core-authentication_type": "local",
|
||||
"core-ldap_admin_groups": "",
|
||||
|
||||
@@ -21,7 +21,6 @@ from modoboa.lib.web_utils import render_to_json_response
|
||||
|
||||
|
||||
class WizardStep(object):
|
||||
|
||||
"""A wizard step."""
|
||||
|
||||
def __init__(self, uid, formclass, title, formtpl=None, new_args=None):
|
||||
@@ -66,7 +65,6 @@ class WizardStep(object):
|
||||
|
||||
|
||||
class WizardForm(object):
|
||||
|
||||
"""Custom wizard."""
|
||||
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
@@ -34,6 +34,7 @@ class DomainLimitsTestCase(lib_tests.ModoTestCase):
|
||||
domain = Domain.objects.get(name="test.com")
|
||||
values = {
|
||||
"name": domain.name, "quota": domain.quota,
|
||||
"default_mailbox_quota": domain.default_mailbox_quota,
|
||||
"enabled": domain.enabled, "type": "domain",
|
||||
"mailboxes_limit": 3, "mailbox_aliases_limit": 3,
|
||||
"domain_aliases_limit": 3, "domain_admins_limit": 3
|
||||
@@ -62,6 +63,7 @@ class DomainLimitsTestCase(lib_tests.ModoTestCase):
|
||||
self.assertFalse(limit.is_exceeded())
|
||||
values = {
|
||||
"name": domain.name, "quota": domain.quota,
|
||||
"default_mailbox_quota": domain.default_mailbox_quota,
|
||||
"enabled": domain.enabled, "type": "domain",
|
||||
"mailboxes_limit": 2, "mailbox_aliases_limit": 2,
|
||||
"domain_aliases_limit": 2, "domain_admins_limit": 2,
|
||||
|
||||
@@ -147,8 +147,8 @@ class UserLimitImportTestCase(LimitImportTestCase):
|
||||
username=self.reseller.username, password="toto")
|
||||
limit = self.reseller.userobjectlimit_set.get(name="domains")
|
||||
self.assertFalse(limit.is_exceeded())
|
||||
f = ContentFile(b"""domain; domain1.com; 100; True
|
||||
domain; domain2.com; 200; False
|
||||
f = ContentFile(b"""domain; domain1.com; 1000; 100; True
|
||||
domain; domain2.com; 1000; 200; False
|
||||
""", name="domains.csv")
|
||||
self.client.post(
|
||||
reverse("admin:domain_import"), {
|
||||
@@ -157,7 +157,7 @@ domain; domain2.com; 200; False
|
||||
)
|
||||
self.assertTrue(limit.is_exceeded())
|
||||
|
||||
f = ContentFile(b"""domain; domain3.com; 100; True
|
||||
f = ContentFile(b"""domain; domain3.com; 1000; 100; True
|
||||
""", name="domains.csv")
|
||||
response = self.client.post(
|
||||
reverse("admin:domain_import"), {
|
||||
|
||||
@@ -78,7 +78,8 @@ class ResourceTestCase(lib_tests.ModoTestCase):
|
||||
|
||||
def _create_domain(self, name, status=200, withtpl=False):
|
||||
values = {
|
||||
"name": name, "quota": 100, "create_dom_admin": False,
|
||||
"name": name, "quota": 100, "default_mailbox_quota": 10,
|
||||
"create_dom_admin": False,
|
||||
"create_aliases": False, "stepid": "step3", "type": "domain"
|
||||
}
|
||||
if withtpl:
|
||||
@@ -95,16 +96,17 @@ class ResourceTestCase(lib_tests.ModoTestCase):
|
||||
def _domain_alias_operation(self, optype, domain, name, status=200):
|
||||
dom = Domain.objects.get(name=domain)
|
||||
values = {
|
||||
'name': dom.name, 'quota': dom.quota, 'enabled': dom.enabled,
|
||||
"type": "domain"
|
||||
"name": dom.name, "quota": dom.quota, "enabled": dom.enabled,
|
||||
"type": "domain",
|
||||
"default_mailbox_quota": dom.default_mailbox_quota,
|
||||
}
|
||||
aliases = [alias.name for alias in dom.domainalias_set.all()]
|
||||
if optype == 'add':
|
||||
if optype == "add":
|
||||
aliases.append(name)
|
||||
else:
|
||||
aliases.remove(name)
|
||||
for cpt, alias in enumerate(aliases):
|
||||
fname = 'aliases' if not cpt else 'aliases_%d' % cpt
|
||||
fname = "aliases" if not cpt else "aliases_%d" % cpt
|
||||
values[fname] = alias
|
||||
self.ajax_post(
|
||||
reverse("admin:domain_change", args=[dom.id]),
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-02-15 08:48
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('relaydomains', '0005_auto_20161105_1426'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='relaydomain',
|
||||
name='last_modification',
|
||||
field=models.DateTimeField(auto_now=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
@@ -23,7 +23,8 @@ class Operations(object):
|
||||
values = {
|
||||
"name": name, "create_dom_admin": False, "type": "relaydomain",
|
||||
"target_host": "external.host.tld", "target_port": 25,
|
||||
"service": srv.id, "enabled": True, "stepid": "step3"
|
||||
"service": srv.id, "enabled": True, "stepid": "step3",
|
||||
"quota": 0, "default_mailbox_quota": 0
|
||||
}
|
||||
return self.ajax_post(
|
||||
reverse("admin:domain_add"),
|
||||
@@ -35,7 +36,8 @@ class Operations(object):
|
||||
values = {
|
||||
"name": rdom.domain.name, "target_host": rdom.target_host,
|
||||
"target_port": rdom.target_port,
|
||||
"type": "relaydomain", "service": rdom.service.id
|
||||
"type": "relaydomain", "service": rdom.service.id,
|
||||
"quota": 0, "default_mailbox_quota": 0
|
||||
}
|
||||
aliases = [alias.name for alias in rdom.domain.domainalias_set.all()]
|
||||
if optype == 'add':
|
||||
@@ -144,7 +146,8 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
|
||||
values = {
|
||||
"name": "relaydomain.org", "target_host": self.rdom.target_host,
|
||||
"target_port": 4040, "type": "relaydomain", "enabled": True,
|
||||
"service": self.rdom.service.id
|
||||
"service": self.rdom.service.id,
|
||||
"quota": 0, "default_mailbox_quota": 0
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:domain_change", args=[self.rdom.domain.id]),
|
||||
@@ -159,6 +162,8 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
|
||||
values = {
|
||||
"name": "relaydomain.tld",
|
||||
"type": "domain",
|
||||
"quota": 0,
|
||||
"default_mailbox_quota": 0,
|
||||
"enabled": True,
|
||||
"target_host": self.rdom.target_host,
|
||||
"target_port": self.rdom.target_port,
|
||||
@@ -176,6 +181,8 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
|
||||
"name": "relaydomain.tld",
|
||||
"type": "relaydomain",
|
||||
"enabled": True,
|
||||
"quota": 0,
|
||||
"default_mailbox_quota": 0
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse("admin:domain_change", args=[domain_pk]), values)
|
||||
@@ -195,7 +202,8 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
|
||||
"name": "relaydomain.org", "target_host": self.rdom.target_host,
|
||||
"target_port": self.rdom.target_port,
|
||||
"type": "relaydomain", "service": self.rdom.service.id,
|
||||
"aliases": "relaydomainalias.net"
|
||||
"aliases": "relaydomainalias.net",
|
||||
"quota": 0, "default_mailbox_quota": 0
|
||||
}
|
||||
self.ajax_post(
|
||||
reverse('admin:domain_change',
|
||||
|
||||
Reference in New Issue
Block a user