Handle destination port.

fix #1003

Conflicts:
	modoboa/relaydomains/factories.py
	modoboa/relaydomains/handlers.py
	modoboa/relaydomains/tests.py
This commit is contained in:
Antoine Nguyen
2017-01-16 17:34:23 +01:00
parent 95aa4a2609
commit dc5155ee68
8 changed files with 93 additions and 72 deletions
-34
View File
@@ -1,34 +0,0 @@
"""Factories."""
import factory
from modoboa.admin.factories import DomainFactory
from modoboa.core.factories import PermissionFactory
from . import models
class ServiceFactory(factory.DjangoModelFactory):
"""Factory to create Service instances."""
class Meta:
model = models.Service
django_get_or_create = ('name', )
name = "dummy"
class RelayDomainFactory(PermissionFactory):
"""Factory to create RelayDomain instances."""
class Meta:
model = models.RelayDomain
django_get_or_create = ("domain", )
target_host = "external.host.tld"
domain = factory.SubFactory(DomainFactory)
verify_recipients = True
service = factory.SubFactory(ServiceFactory)
+24 -13
View File
@@ -1,11 +1,11 @@
"""
Postfix relay domains extension forms.
"""
from django import forms
from django.utils.translation import ugettext_lazy
"""Postfix relay domains extension forms."""
from django import forms
from django.core import validators
from django.utils.translation import ugettext as _
from modoboa.lib.fields import DomainNameField
from modoboa.lib.form_utils import WizardStep
from modoboa.lib import validators as lib_validators
from .models import RelayDomain
@@ -20,14 +20,8 @@ class RelayDomainWizardStep(WizardStep):
class RelayDomainFormGeneral(forms.ModelForm):
"""RelayDomain form."""
name = DomainNameField(
label=ugettext_lazy("Name"),
help_text=ugettext_lazy("The relay domain name")
)
class Meta:
model = RelayDomain
exclude = ["domain", "creation", "last_modification"]
@@ -41,6 +35,22 @@ class RelayDomainFormGeneral(forms.ModelForm):
"service": 3
}
def clean_target_host(self):
"""Check that target host is valid."""
validator_list = [
lib_validators.validate_hostname,
validators.validate_ipv46_address
]
value = self.cleaned_data.get("target_host")
for validator in validator_list:
try:
validator(value)
except forms.ValidationError:
pass
else:
return value
raise forms.ValidationError(_("Invalid value"), code="invalid")
def save(self, *args, **kwargs):
"""Custom save method."""
domain = kwargs.get("domain")
@@ -50,5 +60,6 @@ class RelayDomainFormGeneral(forms.ModelForm):
return None
if domain:
instance.domain = domain
instance.save()
if instance.domain.type == "relaydomain":
instance.save()
return instance
+10 -6
View File
@@ -39,14 +39,18 @@ def clean_domain(sender, instance, **kwargs):
"""Remove or create RelayDomain record if needed."""
if kwargs.get("created"):
return
has_relaydom = hasattr(instance, "relaydomain")
if instance.type == "domain" and has_relaydom:
instance.relaydomain.delete()
elif instance.type == "relaydomain" and not has_relaydom:
if instance.type == "domain":
try:
instance.relaydomain.delete()
except models.RelayDomain.DoesNotExist:
pass
else:
# Make sure to create a RelayDomain instance since we can't do it
# at form level...
models.RelayDomain.objects.create(
domain=instance, service=models.Service.objects.first())
models.RelayDomain.objects.get_or_create(
domain=instance,
defaults={"service": models.Service.objects.first()}
)
@receiver(core_signals.register_postfix_maps)
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.12 on 2017-01-16 14:08
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('relaydomains', '0002_migrate_from_modoboa_admin_relaydomains'),
]
operations = [
migrations.AddField(
model_name='relaydomain',
name='target_port',
field=models.IntegerField(default=25, help_text='Remote port of this domain', verbose_name='target host port'),
),
migrations.AlterField(
model_name='relaydomain',
name='target_host',
field=models.CharField(help_text='Remote address (hostname or IP) of this domain', max_length=255, verbose_name='target host address'),
),
]
+9 -2
View File
@@ -67,8 +67,15 @@ class RelayDomain(admin_models.AdminObject):
domain = models.OneToOneField("admin.Domain", null=True)
target_host = models.CharField(
ugettext_lazy('target host'), max_length=255,
help_text=ugettext_lazy('Remote destination of this domain')
ugettext_lazy("target host address"), max_length=255,
help_text=ugettext_lazy(
"Remote address (hostname or IP) of this domain")
)
target_port = models.IntegerField(
ugettext_lazy("target host port"),
help_text=ugettext_lazy(
"Remote port of this domain"),
default=25
)
service = models.ForeignKey(Service)
verify_recipients = models.BooleanField(
+6 -3
View File
@@ -26,7 +26,8 @@ class RelayDomainsTransportMap(object):
filename = "sql-relaydomains-transport.cf"
mysql = (
"SELECT CONCAT(srv.name, ':[', rdom.target_host, ']') "
"SELECT CONCAT(srv.name, ':[', rdom.target_host, ']:'"
", rdom.target_port) "
"FROM postfix_relay_domains_service AS srv "
"INNER JOIN postfix_relay_domains_relaydomain AS rdom "
"ON rdom.service_id=srv.id "
@@ -34,7 +35,8 @@ class RelayDomainsTransportMap(object):
"WHERE dom.enabled=1 AND dom.name='%s'"
)
postgres = (
"SELECT srv.name || ':[' || rdom.target_host || ']' "
"SELECT srv.name || ':[' || rdom.target_host || ']:' || "
"rdom.target_port "
"FROM postfix_relay_domains_service AS srv "
"INNER JOIN postfix_relay_domains_relaydomain AS rdom "
"ON rdom.service_id=srv.id "
@@ -42,7 +44,8 @@ class RelayDomainsTransportMap(object):
"WHERE dom.enabled AND dom.name='%s'"
)
sqlite = (
"SELECT srv.name || ':[' || rdom.target_host || ']' "
"SELECT srv.name || ':[' || rdom.target_host || ']:' || "
"rdom.target_host "
"FROM postfix_relay_domains_service AS srv "
"INNER JOIN postfix_relay_domains_relaydomain AS rdom "
"ON rdom.service_id=srv.id "
@@ -1,5 +1,6 @@
{% load form_tags %}
{% render_field form.target_host %}
{% render_field form.target_port %}
{% include "relaydomains/service_field.html" with field=form.service label_width="col-sm-4" %}
{% render_field form.verify_recipients %}
+18 -14
View File
@@ -13,7 +13,6 @@ from modoboa.lib.tests import ModoTestCase
from modoboa.lib.test_utils import MapFilesTestCaseMixin
from modoboa.limits import utils as limits_utils
from .factories import RelayDomainFactory
from . import models
@@ -23,8 +22,8 @@ class Operations(object):
srv, created = models.Service.objects.get_or_create(name='dummy')
values = {
"name": name, "create_dom_admin": False, "type": "relaydomain",
"target_host": "external.host.tld", "service": srv.id,
"enabled": True, "stepid": "step3"
"target_host": "external.host.tld", "target_port": 25,
"service": srv.id, "enabled": True, "stepid": "step3"
}
return self.ajax_post(
reverse("admin:domain_add"),
@@ -35,6 +34,7 @@ class Operations(object):
rdom = models.RelayDomain.objects.get(domain__name=rdomain)
values = {
"name": rdom.domain.name, "target_host": rdom.target_host,
"target_port": rdom.target_port,
"type": "relaydomain", "service": rdom.service.id
}
aliases = [alias.name for alias in rdom.domain.domainalias_set.all()]
@@ -64,9 +64,11 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
"""Create test data."""
super(RelayDomainsTestCase, cls).setUpTestData()
admin_factories.populate_database()
cls.rdom = RelayDomainFactory(domain__name="relaydomain.tld")
cls.rdom.domain.type = "relaydomain"
cls.rdom.domain.save()
dom = admin_factories.DomainFactory(
name="relaydomain.tld", type="relaydomain")
dom.relaydomain.target_host = "external.host.tld"
dom.relaydomain.save()
cls.rdom = dom.relaydomain
admin_factories.DomainAliasFactory(
name="relaydomainalias.tld", target=cls.rdom.domain)
admin_factories.MailboxFactory(
@@ -141,28 +143,29 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
"""
values = {
"name": "relaydomain.org", "target_host": self.rdom.target_host,
"type": "relaydomain", "enabled": True,
"target_port": 4040, "type": "relaydomain", "enabled": True,
"service": self.rdom.service.id
}
self.ajax_post(
reverse("admin:domain_change",
args=[self.rdom.domain.id]),
reverse("admin:domain_change", args=[self.rdom.domain.id]),
values
)
models.RelayDomain.objects.get(domain__name='relaydomain.org')
self.rdom.refresh_from_db()
self.assertEqual(self.rdom.target_port, 4040)
def test_relaydomain_domain_switch(self):
"""Check domain <-> relaydomain transitions."""
domain = self.rdom.domain
domain_pk = self.rdom.domain.pk
values = {
"name": "relaydomain.tld",
"type": "domain",
"enabled": True,
"target_host": self.rdom.target_host,
"target_port": self.rdom.target_port,
"service": self.rdom.service.pk
}
self.ajax_post(
reverse("admin:domain_change", args=[domain.pk]), values)
reverse("admin:domain_change", args=[domain_pk]), values)
self.assertFalse(
models.RelayDomain.objects.filter(domain=domain).exists())
self.assertEqual(
@@ -174,7 +177,7 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
"enabled": True,
}
self.ajax_post(
reverse("admin:domain_change", args=[domain.pk]), values)
reverse("admin:domain_change", args=[domain_pk]), values)
self.assertEqual(
admin_models.Domain.objects.get(name="relaydomain.tld").type,
"relaydomain")
@@ -189,6 +192,7 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
"""
values = {
"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"
}
@@ -246,7 +250,7 @@ class ImportTestCase(ModoTestCase):
def test_webui_import(self):
"""Check if import from webui works."""
f = ContentFile("relaydomain;relay.com;127.0.0.1;relay;True;True",
f = ContentFile("relaydomain;relay.com;127.0.0.1;25;relay;True;True",
name="domains.csv")
self.client.post(
reverse("admin:domain_import"), {