Skip to content
Permalink
Browse files
Generic transport editor. (#1309)
Generic transport editor.

see #1301

* Fixed unit test.

* Added unit tests.

* Fixed unit test.

* Added transport module to test list.

* Moved relay transport backend to appropriate app.

see #1301

* Added missing file.
  • Loading branch information
tonioo committed Nov 27, 2017
1 parent 1129c94 commit 98eea78
Show file tree
Hide file tree
Showing 65 changed files with 1,620 additions and 610 deletions.
@@ -12,3 +12,6 @@ DEV
modoboa.iml
.tox
modoboa_test
.coverage
build/
dist/
@@ -4,6 +4,7 @@ cache: pip
python:
- "2.7"
- "3.4"
- "3.6"
addons:
apt:
packages:
@@ -43,7 +44,7 @@ before_script:
script:
- python ./tests.py
- cd test_project
- coverage run --source ../modoboa manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.relaydomains
- coverage run --source ../modoboa manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.transport modoboa.relaydomains

after_success:
- codecov
@@ -42,3 +42,15 @@ file_filter = modoboa/admin/locale/<lang>/LC_MESSAGES/djangojs.po
source_file = modoboa/admin/locale/en/LC_MESSAGES/djangojs.po
source_lang = en
type = PO

[modoboa.transport-djangopo]
file_filter = modoboa/transport/locale/<lang>/LC_MESSAGES/django.po
source_file = modoboa/transport/locale/en/LC_MESSAGES/django.po
source_lang = en
type = PO

[modoboa.transport-djangojspo]
file_filter = modoboa/transport/locale/<lang>/LC_MESSAGES/djangojs.po
source_file = modoboa/transport/locale/en/LC_MESSAGES/djangojs.po
source_lang = en
type = PO
@@ -2,6 +2,9 @@

from __future__ import unicode_literals

from django.utils.translation import ugettext_lazy as _


DNSBL_PROVIDERS = [
"aspews.ext.sorbs.net",
"b.barracudacentral.org",
@@ -91,3 +94,8 @@
"localhost",
"test"
]

DOMAIN_TYPES = [
("domain", _("Domain")),
("relaydomain", _("Relay domain")),
]
@@ -20,6 +20,7 @@
from modoboa.lib.web_utils import render_to_json_response
from modoboa.parameters import tools as param_tools

from .. import constants
from .. import lib
from .. import signals

@@ -28,11 +29,6 @@
)


DOMAIN_TYPES = [
("domain", _("Domain")),
]


class DomainFormGeneral(forms.ModelForm, DynamicForm):
"""A form to create/edit a domain."""

@@ -63,12 +59,7 @@ def __init__(self, user, *args, **kwargs):
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(
sender=self.__class__)]
)
self.fields["type"].choices = DOMAIN_TYPES + extra_domain_types
self.fields["type"].choices = constants.DOMAIN_TYPES
self.field_widths = {
"quota": 3,
"default_mailbox_quota": 3
@@ -382,10 +373,13 @@ def save(self):
first_form = self.forms[0]["instance"]
options = {}
if isinstance(first_form, DomainFormGeneral):
options["domalias_post_create"] = True
first_form.save(self.request.user, **options)
domain = first_form.save(
self.request.user, domalias_post_create=True)
options.update({"domain": domain})
else:
first_form.save(self.request.user)
for f in self.forms[1:]:
f["instance"].save(self.request.user)
f["instance"].save(self.request.user, **options)

def done(self):
return render_to_json_response(_("Domain modified"))
@@ -5,11 +5,27 @@
from django.db import models
from django.utils import timezone

from django.contrib.contenttypes.fields import GenericRelation

from modoboa.core import models as core_models
from modoboa.lib.permissions import (
grant_access_to_object, ungrant_access_to_object
)


class AdminObjectManager(models.Manager):

def get_for_admin(self, admin):
"""Return the objects belonging to this admin
The result is a ``QuerySet`` object, so this function can be used
to fill ``ModelChoiceField`` objects.
"""
if admin.is_superuser:
return self.get_queryset()
return self.get_queryset().filter(owners__user=admin)


class AdminObject(models.Model):
"""Abstract model to support dates.
@@ -20,8 +36,11 @@ class AdminObject(models.Model):

creation = models.DateTimeField(default=timezone.now)
last_modification = models.DateTimeField(auto_now=True)
owners = GenericRelation(core_models.ObjectAccess)
_objectname = None

objects = AdminObjectManager()

class Meta:
abstract = True

@@ -3,42 +3,24 @@
from __future__ import unicode_literals

import datetime
from functools import reduce

from django.db import models
from django.db.models.manager import Manager
from django.utils import timezone
from django.utils.encoding import (
python_2_unicode_compatible, smart_text, force_text
)
from django.utils.functional import cached_property
from django.utils.translation import ugettext as _, ugettext_lazy

from django.contrib.contenttypes.fields import GenericRelation

from reversion import revisions as reversion

from modoboa.core import signals as core_signals
from modoboa.core.models import User, ObjectAccess
from modoboa.core.models import User
from modoboa.lib.exceptions import BadRequest, Conflict
from modoboa.parameters import tools as param_tools

from .base import AdminObject
from .. import constants
from .. import signals


class DomainManager(Manager):

def get_for_admin(self, admin):
"""Return the domains belonging to this admin
The result is a ``QuerySet`` object, so this function can be used
to fill ``ModelChoiceField`` objects.
"""
if admin.is_superuser:
return self.get_queryset()
return self.get_queryset().filter(owners__user=admin)


@python_2_unicode_compatible
@@ -67,15 +49,12 @@ class Domain(AdminObject):
help_text=ugettext_lazy("Check to activate this domain"),
default=True
)
owners = GenericRelation(ObjectAccess)
type = models.CharField(default="domain", max_length=20)
enable_dns_checks = models.BooleanField(
ugettext_lazy("Enable DNS checks"), default=True,
help_text=ugettext_lazy("Check to enable DNS checks for this domain")
)

objects = DomainManager()

class Meta:
permissions = (
("view_domain", "View domain"),
@@ -111,11 +90,11 @@ def identities_count(self):

@property
def tags(self):
if self.type == "domain":
return [{"name": "domain", "label": _("Domain"), "type": "dom"}]
results = signals.get_domain_tags.send(
sender=self.__class__, domain=self)
return reduce(lambda a, b: a + b, [result[1] for result in results])
label = ""
for dt in constants.DOMAIN_TYPES:
if self.type == dt[0]:
label = dt[1]
return [{"name": self.type, "label": label, "type": "dom"}]

@property
def admins(self):
@@ -345,6 +345,7 @@ def save(self, *args, **kwargs):
username=self.full_address)
super(Mailbox, self).save(*args, **kwargs)


reversion.register(Mailbox)


@@ -365,6 +366,7 @@ def __str__(self):
"""Return address."""
return smart_text(self.address)


reversion.register(SenderAddress)


@@ -21,12 +21,12 @@
extra_domain_menu_entries = django.dispatch.Signal(providing_args=["user"])
extra_domain_qset_filters = django.dispatch.Signal(
providing_args=["domfilter", "extrafilters"])
extra_domain_types = django.dispatch.Signal()
# extra_domain_types = django.dispatch.Signal()
extra_domain_wizard_steps = django.dispatch.Signal()
get_account_form_instances = django.dispatch.Signal(
providing_args=["user", "account"])
get_domain_form_instances = django.dispatch.Signal(
providing_args=["user", "domain"])
get_domain_tags = django.dispatch.Signal(providing_args=["domain"])
# get_domain_tags = django.dispatch.Signal(providing_args=["domain"])
import_object = django.dispatch.Signal(providing_args=["objtype"])
use_external_recipients = django.dispatch.Signal(providing_args=["recipients"])
@@ -57,7 +57,7 @@ def test_management_command_with_no_alias(self):
"""Check that problem is fixed."""
count, detail = models.Alias.objects.filter(
address="user@test.com", internal=True).delete()
self.assertEqual(count, 2)
self.assertEqual(count, 3)
ret = management.call_command("modo", "repair", "--quiet")
assert ret is None
self.assertTrue(
@@ -45,11 +45,10 @@ def index(request):
)
def _domains(request):
sort_order, sort_dir = get_sort_order(request.GET, "name")
extra_filters = reduce(
lambda a, b: a + b,
[result[1] for result in
signals.extra_domain_filters.send(sender="_domains")]
)
extra_filters = signals.extra_domain_filters.send(sender="_domains")
if extra_filters:
extra_filters = reduce(
lambda a, b: a + b, [result[1] for result in extra_filters])
filters = dict(
(flt, request.GET.get(flt, None))
for flt in ["domfilter", "searchquery"] + extra_filters
@@ -63,6 +63,7 @@ MODOBOA_APPS = (
'modoboa.core',
'modoboa.lib',
'modoboa.admin',
'modoboa.transport',
'modoboa.relaydomains',
'modoboa.limits',
'modoboa.parameters',
@@ -14,7 +14,6 @@

from modoboa.lib.cryptutils import random_key
from modoboa.lib.permissions import add_permissions_to_group
import modoboa.relaydomains.models as relay_models

from ... import constants
from ... import extensions
@@ -58,18 +57,15 @@ def handle(self, *args, **options):
lc.parameters.set_value("secret_key", random_key())
lc.save()

for service_name in ["relay", "smtp"]:
relay_models.Service.objects.get_or_create(name=service_name)

groups = list(constants.PERMISSIONS.keys())
for groupname in groups:
group, created = Group.objects.get_or_create(name=groupname)
results = signals.extra_role_permissions.send(
sender=self.__class__, role=groupname)
permissions = (
constants.PERMISSIONS.get(groupname, []) +
reduce(lambda a, b: a + b, [result[1] for result in results])
)
permissions = constants.PERMISSIONS.get(groupname, [])
if results:
permissions += reduce(
lambda a, b: a + b, [result[1] for result in results])
if not permissions:
continue
add_permissions_to_group(group, permissions)
@@ -120,7 +120,6 @@ class SettingsTestCase(ModoTestCase):
"core-ldap_bind_password": "",
"limits-deflt_domain_domain_aliases_limit": "0",
"core-secret_key": ":?j3]QPWo!.'_c4n",
"relaydomains-master_cf_path": "/etc/postfix/master.cf",
"limits-deflt_domain_domain_admins_limit": "0",
"limits-enable_admin_limits": "True",
"core-ldap_bind_dn": "",
@@ -166,7 +165,7 @@ def test_get_settings(self):
"""Test settings display."""
url = reverse("core:parameters")
response = self.ajax_get(url)
for app in ["core", "admin", "limits", "relaydomains"]:
for app in ["core", "admin", "limits"]:
self.assertIn('data-app="{}"'.format(app), response["content"])

def test_save_settings(self):
@@ -92,7 +92,7 @@ def clean(self):
self.add_error(lname, _("Invalid limit"))
return cleaned_data

def save(self, user):
def save(self, user, **kwargs):
"""Set limits."""
for name, ltpl in utils.get_domain_limit_templates():
fieldname = "{}_limit".format(name)

This file was deleted.

@@ -3,15 +3,6 @@
from __future__ import unicode_literals

from django.apps import AppConfig
from django.utils.translation import ugettext as _


def load_relaydomains_settings():
"""Load application settings."""
from modoboa.parameters import tools as param_tools
from .app_settings import AdminParametersForm

param_tools.registry.add("global", AdminParametersForm, _("Relay domains"))


class RelayDomainsConfig(AppConfig):
@@ -22,5 +13,5 @@ class RelayDomainsConfig(AppConfig):
verbose_name = "Modoboa relay domains"

def ready(self):
load_relaydomains_settings()
from . import handlers
from . import transport

0 comments on commit 98eea78

Please sign in to comment.