websites: Prevent multiple domains on the same port
This commit is contained in:
parent
01842f224b
commit
f2dbc0ed42
|
@ -131,15 +131,17 @@ class PostfixAddressBackend(ServiceController):
|
||||||
self.append('sed -i "/^%(domain)s\s*/d" %(virtual_alias_domains)s' % context)
|
self.append('sed -i "/^%(domain)s\s*/d" %(virtual_alias_domains)s' % context)
|
||||||
|
|
||||||
def update_virtual_alias_maps(self, address, context):
|
def update_virtual_alias_maps(self, address, context):
|
||||||
destination = []
|
# Virtual mailbox stuff
|
||||||
for mailbox in address.get_mailboxes():
|
# destination = []
|
||||||
context['mailbox'] = mailbox
|
# for mailbox in address.get_mailboxes():
|
||||||
destination.append("%(mailbox)s@%(mailbox_domain)s" % context)
|
# context['mailbox'] = mailbox
|
||||||
for forward in address.forward:
|
# destination.append("%(mailbox)s@%(mailbox_domain)s" % context)
|
||||||
if '@' in forward:
|
# for forward in address.forward:
|
||||||
destination.append(forward)
|
# if '@' in forward:
|
||||||
|
# destination.append(forward)
|
||||||
|
destination = address.destination
|
||||||
if destination:
|
if destination:
|
||||||
context['destination'] = ' '.join(destination)
|
context['destination'] = destination
|
||||||
self.append(textwrap.dedent("""
|
self.append(textwrap.dedent("""
|
||||||
LINE="%(email)s\t%(destination)s"
|
LINE="%(email)s\t%(destination)s"
|
||||||
if [[ ! $(grep "^%(email)s\s" %(virtual_alias_maps)s) ]]; then
|
if [[ ! $(grep "^%(email)s\s" %(virtual_alias_maps)s) ]]; then
|
||||||
|
@ -153,7 +155,7 @@ class PostfixAddressBackend(ServiceController):
|
||||||
fi""") % context)
|
fi""") % context)
|
||||||
else:
|
else:
|
||||||
logger.warning("Address %i is empty" % address.pk)
|
logger.warning("Address %i is empty" % address.pk)
|
||||||
self.append('sed -i "/^%(email)s\s/d" %(virtual_alias_maps)s')
|
self.append('sed -i "/^%(email)s\s/d" %(virtual_alias_maps)s' % context)
|
||||||
self.append('UPDATED_VIRTUAL_ALIAS_MAPS=1')
|
self.append('UPDATED_VIRTUAL_ALIAS_MAPS=1')
|
||||||
|
|
||||||
def exclude_virtual_alias_maps(self, context):
|
def exclude_virtual_alias_maps(self, context):
|
||||||
|
@ -180,6 +182,7 @@ class PostfixAddressBackend(ServiceController):
|
||||||
[[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]] && { /etc/init.d/postfix reload; }
|
[[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]] && { /etc/init.d/postfix reload; }
|
||||||
""") % context
|
""") % context
|
||||||
)
|
)
|
||||||
|
self.append('exit 0')
|
||||||
|
|
||||||
def get_context_files(self):
|
def get_context_files(self):
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -111,12 +111,12 @@ class Address(models.Model):
|
||||||
def email(self):
|
def email(self):
|
||||||
return "%s@%s" % (self.name, self.domain)
|
return "%s@%s" % (self.name, self.domain)
|
||||||
|
|
||||||
# @property
|
@cached_property
|
||||||
# def destination(self):
|
def destination(self):
|
||||||
# destinations = list(self.mailboxes.values_list('name', flat=True))
|
destinations = list(self.mailboxes.values_list('name', flat=True))
|
||||||
# if self.forward:
|
if self.forward:
|
||||||
# destinations.append(self.forward)
|
destinations += self.forward
|
||||||
# return ' '.join(destinations)
|
return ' '.join(destinations)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.account_id:
|
if self.account_id:
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.core.urlresolvers import resolve
|
||||||
|
from django.db.models import Q
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
from orchestra.admin import ExtendedModelAdmin
|
from orchestra.admin import ExtendedModelAdmin
|
||||||
from orchestra.admin.utils import admin_link, change_url
|
from orchestra.admin.utils import admin_link, change_url
|
||||||
from orchestra.apps.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
|
from orchestra.apps.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
|
||||||
from orchestra.forms.widgets import DynamicHelpTextSelect
|
from orchestra.forms.widgets import DynamicHelpTextSelect
|
||||||
|
|
||||||
from . import settings
|
from . import settings
|
||||||
|
from .forms import WebsiteAdminForm
|
||||||
from .models import Content, Website, WebsiteOption
|
from .models import Content, Website, WebsiteOption
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,6 +69,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
'fields': ('account_link', 'name', 'port', 'domains', 'is_active'),
|
'fields': ('account_link', 'name', 'port', 'domains', 'is_active'),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
form = WebsiteAdminForm
|
||||||
filter_by_account_fields = ['domains']
|
filter_by_account_fields = ['domains']
|
||||||
list_prefetch_related = ('domains', 'content_set__webapp')
|
list_prefetch_related = ('domains', 'content_set__webapp')
|
||||||
search_fields = ('name', 'account__username', 'domains__name')
|
search_fields = ('name', 'account__username', 'domains__name')
|
||||||
|
@ -91,9 +96,21 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
display_webapps.short_description = _("Web apps")
|
display_webapps.short_description = _("Web apps")
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
if db_field.name == 'root':
|
"""
|
||||||
kwargs['widget'] = forms.TextInput(attrs={'size':'100'})
|
Exclude domains with exhausted ports
|
||||||
return super(WebsiteAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
has to be done here, on the form doesn't work because of filter_by_account_fields
|
||||||
|
"""
|
||||||
|
formfield = super(WebsiteAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
||||||
|
if db_field.name == 'domains':
|
||||||
|
qset = Q()
|
||||||
|
for port, __ in settings.WEBSITES_PORT_CHOICES:
|
||||||
|
qset = qset & Q(websites__port=port)
|
||||||
|
args = resolve(kwargs['request'].path).args
|
||||||
|
if args:
|
||||||
|
object_id = args[0]
|
||||||
|
qset = Q(qset & ~Q(websites__pk=object_id))
|
||||||
|
formfield.queryset = formfield.queryset.exclude(qset)
|
||||||
|
return formfield
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Website, WebsiteAdmin)
|
admin.site.register(Website, WebsiteAdmin)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
from django import forms
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class WebsiteAdminForm(forms.ModelForm):
|
||||||
|
def clean(self):
|
||||||
|
""" Prevent multiples domains on the same port """
|
||||||
|
domains = self.cleaned_data.get('domains')
|
||||||
|
port = self.cleaned_data.get('port')
|
||||||
|
existing = []
|
||||||
|
for domain in domains.all():
|
||||||
|
if domain.websites.filter(port=port).exclude(pk=self.instance.pk).exists():
|
||||||
|
existing.append(domain.name)
|
||||||
|
if existing:
|
||||||
|
context = (', '.join(existing), port)
|
||||||
|
raise ValidationError({
|
||||||
|
'domains': 'A website is already defined for "%s" on port %s' % context
|
||||||
|
})
|
||||||
|
return self.cleaned_data
|
||||||
|
|
|
@ -32,12 +32,6 @@ class Website(models.Model):
|
||||||
def unique_name(self):
|
def unique_name(self):
|
||||||
return "%s-%i" % (self.name, self.pk)
|
return "%s-%i" % (self.name, self.pk)
|
||||||
|
|
||||||
@cached
|
|
||||||
def get_options(self):
|
|
||||||
return {
|
|
||||||
opt.name: opt.value for opt in self.options.all()
|
|
||||||
}
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def protocol(self):
|
def protocol(self):
|
||||||
if self.port == 80:
|
if self.port == 80:
|
||||||
|
@ -46,6 +40,12 @@ class Website(models.Model):
|
||||||
return 'https'
|
return 'https'
|
||||||
raise TypeError('No protocol for port "%s"' % self.port)
|
raise TypeError('No protocol for port "%s"' % self.port)
|
||||||
|
|
||||||
|
@cached
|
||||||
|
def get_options(self):
|
||||||
|
return {
|
||||||
|
opt.name: opt.value for opt in self.options.all()
|
||||||
|
}
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
domain = self.domains.first()
|
domain = self.domains.first()
|
||||||
if domain:
|
if domain:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
@ -49,3 +50,17 @@ class WebsiteSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
||||||
model = Website
|
model = Website
|
||||||
fields = ('url', 'name', 'port', 'domains', 'is_active', 'contents', 'options')
|
fields = ('url', 'name', 'port', 'domains', 'is_active', 'contents', 'options')
|
||||||
postonly_fileds = ('name',)
|
postonly_fileds = ('name',)
|
||||||
|
|
||||||
|
def full_clean(self, instance):
|
||||||
|
""" Prevent multiples domains on the same port """
|
||||||
|
existing = []
|
||||||
|
for domain in instance._m2m_data['domains']:
|
||||||
|
if domain.websites.filter(port=instance.port).exclude(pk=instance.pk).exists():
|
||||||
|
existing.append(domain.name)
|
||||||
|
if existing:
|
||||||
|
context = (', '.join(existing), instance.port)
|
||||||
|
raise ValidationError({
|
||||||
|
'domains': 'A website is already defined for "%s" on port %s' % context
|
||||||
|
})
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue