Improved orchestration.server validation logic

This commit is contained in:
Marc Aymerich 2016-02-03 14:19:50 +00:00
parent db652484c1
commit e74964417a
4 changed files with 55 additions and 8 deletions

View File

@ -44,6 +44,13 @@ class MailboxForm(forms.ModelForm):
if self.instance and self.instance.pk: if self.instance and self.instance.pk:
self.fields['addresses'].initial = self.instance.addresses.all() self.fields['addresses'].initial = self.instance.addresses.all()
def clean_name(self):
name = self.cleaned_data['name']
max_length = settings.MAILBOXES_NAME_MAX_LENGTH
if len(name) > max_length:
raise ValidationError("Name length should be less than %i" % max_length)
return name
class MailboxChangeForm(UserChangeForm, MailboxForm): class MailboxChangeForm(UserChangeForm, MailboxForm):

View File

@ -20,6 +20,12 @@ MAILBOXES_DOMAIN_MODEL = Setting('MAILBOXES_DOMAIN_MODEL', 'domains.Domain',
) )
MAILBOXES_NAME_MAX_LENGTH = Setting('MAILBOXES_NAME_MAX_LENGTH',
64,
help_text=_("Limit for system user based mailbox on Linux should be 32.")
)
MAILBOXES_HOME = Setting('MAILBOXES_HOME', MAILBOXES_HOME = Setting('MAILBOXES_HOME',
'/home/%(name)s', '/home/%(name)s',
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_names), help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_names),

View File

@ -3,13 +3,14 @@ import socket
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.module_loading import autodiscover_modules from django.utils.module_loading import autodiscover_modules
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.core.validators import validate_ip_address, ValidationError from orchestra.core.validators import validate_ip_address, validate_hostname, OrValidator
from orchestra.models.fields import NullableCharField, MultiSelectField from orchestra.models.fields import NullableCharField, MultiSelectField
from . import settings from . import settings
@ -21,9 +22,13 @@ logger = logging.getLogger(__name__)
class Server(models.Model): class Server(models.Model):
""" Machine runing daemons (services) """ """ Machine runing daemons (services) """
name = models.CharField(_("name"), max_length=256, unique=True) name = models.CharField(_("name"), max_length=256, unique=True,
help_text=_("Verbose name or hostname of this server."))
address = NullableCharField(_("address"), max_length=256, blank=True, address = NullableCharField(_("address"), max_length=256, blank=True,
null=True, unique=True, help_text=_("IP address or domain name")) validators=[OrValidator(validate_ip_address, validate_hostname)],
null=True, unique=True, help_text=_(
"Optional IP address or domain name. Name field will be used if not provided.<br>"
"If the IP address never change you can set this field and save DNS requests."))
description = models.TextField(_("description"), blank=True) description = models.TextField(_("description"), blank=True)
os = models.CharField(_("operative system"), max_length=32, os = models.CharField(_("operative system"), max_length=32,
choices=settings.ORCHESTRATION_OS_CHOICES, choices=settings.ORCHESTRATION_OS_CHOICES,
@ -38,14 +43,24 @@ class Server(models.Model):
return self.name return self.name
def get_ip(self): def get_ip(self):
if self.address: address = self.get_address()
return self.address
try: try:
validate_ip_address(self.name) return validate_ip_address(address)
except ValidationError: except ValidationError:
return socket.gethostbyname(self.name) return socket.gethostbyname(self.name)
else:
return self.name def clean(self):
self.name = self.name.strip()
self.address = self.address.strip()
if self.name and not self.address:
validate = OrValidator(validate_ip_address, validate_hostname)
validate_hostname(self.name)
try:
validate(self.name)
except ValidationError as err:
raise ValidationError({
'name': _("Name should be a valid hostname or IP address when address is not provided.")
})
class BackendLog(models.Model): class BackendLog(models.Model):

View File

@ -37,6 +37,25 @@ def all_valid(*args):
raise ValidationError(errors) raise ValidationError(errors)
class OrValidator(object):
"""
Run validators with an OR logic
"""
def __init__(self, *validators):
self.validators = validators
def __call__(self, value):
msg = []
for validator in self.validators:
try:
validator(value)
except ValidationError as err:
msg.append(str(err))
else:
return
raise ValidationError(' OR '.join(msg))
def validate_ipv4_address(value): def validate_ipv4_address(value):
msg = _("Not a valid IPv4 address") msg = _("Not a valid IPv4 address")
try: try: