diff --git a/TODO.md b/TODO.md
index 5c4f68c5..a3c51160 100644
--- a/TODO.md
+++ b/TODO.md
@@ -426,3 +426,6 @@ Case
# Discount prepaid metric should be more optimal https://orchestra.pangea.org/admin/orders/order/40/
# -> order.billed_metric besides billed_until
+
+
+# websites directives: redirect strip() and allow empty URL_path
diff --git a/orchestra/contrib/lists/serializers.py b/orchestra/contrib/lists/serializers.py
index ad6f2381..be44f37b 100644
--- a/orchestra/contrib/lists/serializers.py
+++ b/orchestra/contrib/lists/serializers.py
@@ -34,13 +34,11 @@ class ListSerializer(AccountSerializerMixin, SetPasswordHyperlinkedSerializer):
fields = ('url', 'id', 'name', 'password', 'address_name', 'address_domain', 'admin_email')
postonly_fields = ('name', 'password')
- def validate_address_domain(self, attrs, source):
- address_domain = attrs.get(source)
- address_name = attrs.get('address_name')
+ def validate_address_domain(self, address_name):
if self.instance:
address_domain = address_domain or self.instance.address_domain
address_name = address_name or self.instance.address_name
if address_name and not address_domain:
raise serializers.ValidationError(
_("address_domains should should be provided when providing an addres_name"))
- return attrs
+ return address_name
diff --git a/orchestra/contrib/payments/serializers.py b/orchestra/contrib/payments/serializers.py
index b026e6c2..e423abbb 100644
--- a/orchestra/contrib/payments/serializers.py
+++ b/orchestra/contrib/payments/serializers.py
@@ -11,13 +11,15 @@ class PaymentSourceSerializer(AccountSerializerMixin, serializers.HyperlinkedMod
model = PaymentSource
fields = ('url', 'id', 'method', 'data', 'is_active')
- def validate_data(self, attrs, source):
- plugin = PaymentMethod.get(attrs['method'])
+ def validate(self, data):
+ """ validate data according to method """
+ data = super(PaymentSourceSerializer, self).validate(data)
+ plugin = PaymentMethod.get(data['method'])
serializer_class = plugin().get_serializer()
- serializer = serializer_class(data=attrs[source])
+ serializer = serializer_class(data=data['data'])
if not serializer.is_valid():
raise serializers.ValidationError(serializer.errors)
- return attrs
+ return data
def transform_data(self, obj, value):
if not obj:
diff --git a/orchestra/contrib/resources/serializers.py b/orchestra/contrib/resources/serializers.py
index fa21610c..0ffadf2f 100644
--- a/orchestra/contrib/resources/serializers.py
+++ b/orchestra/contrib/resources/serializers.py
@@ -48,9 +48,8 @@ def insert_resource_serializers():
except KeyError:
continue
# TODO this is a fucking workaround, reimplement this on the proper place
- def validate_resources(self, attrs, source, _resources=resources):
+ def validate_resources(self, posted, _resources=resources):
""" Creates missing resources """
- posted = attrs.get(source, [])
result = []
resources = list(_resources)
for data in posted:
@@ -67,8 +66,7 @@ def insert_resource_serializers():
if not resource.on_demand:
data.allocated = resource.default_allocation
result.append(data)
- attrs[source] = result
- return attrs
+ return result
viewset = router.get_viewset(model)
viewset.serializer_class.validate_resources = validate_resources
diff --git a/orchestra/contrib/systemusers/forms.py b/orchestra/contrib/systemusers/forms.py
index 886f493f..dc30fbfd 100644
--- a/orchestra/contrib/systemusers/forms.py
+++ b/orchestra/contrib/systemusers/forms.py
@@ -62,6 +62,10 @@ class SystemUserFormMixin(object):
};""" % username
)
+ def clean_directory(self):
+ directory = self.cleaned_data['directory']
+ return directory.lstrip('/')
+
def clean(self):
super(SystemUserFormMixin, self).clean()
cleaned_data = self.cleaned_data
@@ -113,6 +117,10 @@ class PermissionForm(forms.Form):
(user.get_base_home(), user.get_base_home()) for user in related_users
)
+ def clean_home_extension(self):
+ home_extension = self.cleaned_data['home_extension']
+ return home_extension.lstrip('/')
+
def clean(self):
cleaned_data = super(PermissionForm, self).clean()
path = os.path.join(cleaned_data['base_home'], cleaned_data['home_extension'])
diff --git a/orchestra/contrib/systemusers/models.py b/orchestra/contrib/systemusers/models.py
index 1b7c640f..62798d2c 100644
--- a/orchestra/contrib/systemusers/models.py
+++ b/orchestra/contrib/systemusers/models.py
@@ -96,6 +96,7 @@ class SystemUser(models.Model):
super(SystemUser, self).save(*args, **kwargs)
def clean(self):
+ self.directory = self.directory.lstrip('/')
if self.home:
self.home = os.path.normpath(self.home)
if self.directory:
diff --git a/orchestra/contrib/systemusers/serializers.py b/orchestra/contrib/systemusers/serializers.py
index 05c64f51..e9cf1257 100644
--- a/orchestra/contrib/systemusers/serializers.py
+++ b/orchestra/contrib/systemusers/serializers.py
@@ -24,20 +24,20 @@ class SystemUserSerializer(AccountSerializerMixin, SetPasswordHyperlinkedSeriali
)
postonly_fields = ('username', 'password')
- def validate(self, attrs):
- attrs = super(SystemUserSerializer, self).validate(attrs)
- user = SystemUser(
- username=attrs.get('username') or self.instance.username,
- shell=attrs.get('shell') or self.instance.shell,
- )
- validate_home(user, attrs, self.get_account())
- return attrs
+ def validate_directory(self, directory):
+ return directory.lstrip('/')
- def validate_groups(self, attrs, source):
- groups = attrs.get(source)
+ def validate(self, data):
+ data = super(SystemUserSerializer, self).validate(data)
+ user = SystemUser(
+ username=data.get('username') or self.instance.username,
+ shell=data.get('shell') or self.instance.shell,
+ )
+ validate_home(user, data, self.get_account())
+ groups = data.get('groups')
if groups:
for group in groups:
- if group.username == attrs['username']:
+ if group.username == data['username']:
raise serializers.ValidationError(
_("Do not make the user member of its group"))
- return attrs
+ return data
diff --git a/orchestra/contrib/systemusers/validators.py b/orchestra/contrib/systemusers/validators.py
index 3c5f0839..9dda0890 100644
--- a/orchestra/contrib/systemusers/validators.py
+++ b/orchestra/contrib/systemusers/validators.py
@@ -6,7 +6,7 @@ from django.utils.translation import ugettext_lazy as _
from orchestra.contrib.orchestration import Operation
-def validate_path_exists(user, path, ):
+def validate_path_exists(user, path):
user.path_to_validate = path
log = Operation.execute_action(user, 'validate_path_exists')[0]
if 'path does not exists' in log.stderr:
diff --git a/orchestra/contrib/websites/directives.py b/orchestra/contrib/websites/directives.py
index 6038e210..65922d91 100644
--- a/orchestra/contrib/websites/directives.py
+++ b/orchestra/contrib/websites/directives.py
@@ -84,12 +84,13 @@ class SiteDirective(Plugin):
if errors:
raise ValidationError(errors)
- def validate(self, website):
- if self.regex and not re.match(self.regex, website.value):
+ def validate(self, directive):
+ directive.value = directive.value.strip()
+ if self.regex and not re.match(self.regex, directive.value):
raise ValidationError({
'value': ValidationError(_("'%(value)s' does not match %(regex)s."),
params={
- 'value': website.value,
+ 'value': directive.value,
'regex': self.regex
}),
})
@@ -99,20 +100,25 @@ class Redirect(SiteDirective):
name = 'redirect'
verbose_name = _("Redirection")
help_text = _("<website path> <destination URL>")
- regex = r'^[^ ]+\s[^ ]+$'
+ regex = r'^[^ ]*\s[^ ]+$'
group = SiteDirective.HTTPD
unique_value = True
unique_location = True
+
+ def validate(self, directive):
+ """ inserts default url path if not provided """
+ values = directive.value.strip().split()
+ if len(values) == 1:
+ values.insert(0, '/')
+ directive.value = ' '.join(values)
+ super(Redirect, self).validate(directive)
-class Proxy(SiteDirective):
+class Proxy(Redirect):
name = 'proxy'
verbose_name = _("Proxy")
help_text = _("<website path> <target URL>")
regex = r'^[^ ]+\shttp[^ ]+(timeout=[0-9]{1,3}|retry=[0-9]|\s)*$'
- group = SiteDirective.HTTPD
- unique_value = True
- unique_location = True
class ErrorDocument(SiteDirective):
@@ -132,27 +138,21 @@ class SSLCA(SiteDirective):
name = 'ssl-ca'
verbose_name = _("SSL CA")
help_text = _("Filesystem path of the CA certificate file.")
- regex = r'^[^ ]+$'
+ regex = r'^/[^ ]+$'
group = SiteDirective.SSL
unique_name = True
-class SSLCert(SiteDirective):
+class SSLCert(SSLCA):
name = 'ssl-cert'
verbose_name = _("SSL cert")
help_text = _("Filesystem path of the certificate file.")
- regex = r'^[^ ]+$'
- group = SiteDirective.SSL
- unique_name = True
-class SSLKey(SiteDirective):
+class SSLKey(SSLCA):
name = 'ssl-key'
verbose_name = _("SSL key")
help_text = _("Filesystem path of the key file.")
- regex = r'^[^ ]+$'
- group = SiteDirective.SSL
- unique_name = True
class SecRuleRemove(SiteDirective):
@@ -164,13 +164,11 @@ class SecRuleRemove(SiteDirective):
unique_location = True
-class SecEngine(SiteDirective):
+class SecEngine(SecRuleRemove):
name = 'sec-engine'
verbose_name = _("SecRuleEngine Off")
help_text = _("URL path with disabled modsecurity engine.")
regex = r'^/[^ ]*$'
- group = SiteDirective.SEC
- unique_value = True
class WordPressSaaS(SiteDirective):
@@ -183,21 +181,13 @@ class WordPressSaaS(SiteDirective):
unique_location = True
-class DokuWikiSaaS(SiteDirective):
+class DokuWikiSaaS(WordPressSaaS):
name = 'dokuwiki-saas'
verbose_name = "DokuWiki SaaS"
help_text = _("URL path for mounting wordpress multisite.")
- group = SiteDirective.SAAS
- regex = r'^/[^ ]*$'
- unique_value = True
- unique_location = True
-class DrupalSaaS(SiteDirective):
+class DrupalSaaS(WordPressSaaS):
name = 'drupal-saas'
verbose_name = "Drupdal SaaS"
help_text = _("URL path for mounting wordpress multisite.")
- group = SiteDirective.SAAS
- regex = r'^/[^ ]*$'
- unique_value = True
- unique_location = True