[sources] Check source's url attribute value on creation/modification
Similarly as for config. Now, ldap source validation is properly done there
instead of at initialization time.
--- a/cubicweb/hooks/syncsources.py Wed Apr 12 16:07:25 2017 +0200
+++ b/cubicweb/hooks/syncsources.py Wed Apr 12 16:10:57 2017 +0200
@@ -51,6 +51,7 @@
raise validation_error(self.entity, {('type', 'subject'): msg})
source = self.get_source(self.entity)
+ source.check_urls(self.entity)
source.check_config(self.entity)
@@ -76,5 +77,7 @@
raise validation_error(self.entity, {('name', 'subject'): msg})
source = self.get_source(self.entity)
+ if 'url' in self.entity.cw_edited:
+ source.check_urls(self.entity)
if 'config' in self.entity.cw_edited:
source.check_config(self.entity)
--- a/cubicweb/hooks/test/unittest_syncsources.py Wed Apr 12 16:07:25 2017 +0200
+++ b/cubicweb/hooks/test/unittest_syncsources.py Wed Apr 12 16:10:57 2017 +0200
@@ -26,8 +26,15 @@
with self.admin_access.cnx() as cnx:
source = cnx.find('CWSource').one()
- with self.assertRaises(ValidationError):
+ with self.assertRaises(ValidationError) as cm:
+ source.cw_set(url=u'whatever')
+ self.assertIn("Configuration of the system source goes to the 'sources' file",
+ str(cm.exception))
+
+ with self.assertRaises(ValidationError) as cm:
source.cw_set(config=u'whatever')
+ self.assertIn("Configuration of the system source goes to the 'sources' file",
+ str(cm.exception))
if __name__ == '__main__':
--- a/cubicweb/server/sources/__init__.py Wed Apr 12 16:07:25 2017 +0200
+++ b/cubicweb/server/sources/__init__.py Wed Apr 12 16:10:57 2017 +0200
@@ -184,6 +184,17 @@
"""
return cls._check_config_dict(source_entity.eid, source_entity.dictconfig)
+ def check_urls(self, source_entity):
+ """Check URL of source entity: `urls` is a string that may contain one
+ URL per line), and return a list of at least one validated URL.
+ """
+ urls = source_entity.url if source_entity.url else ''
+ urls = [url.strip() for url in urls.splitlines() if url.strip()]
+ if not urls:
+ msg = _('specifying an URL is mandatory')
+ raise ValidationError(source_entity.eid, {role_name('url', 'subject'): msg})
+ return urls
+
# source initialization / finalization #####################################
def set_schema(self, schema):
@@ -200,8 +211,7 @@
"""
source_entity.complete()
if source_entity.url:
- self.urls = [url.strip() for url in source_entity.url.splitlines()
- if url.strip()]
+ self.urls = self.check_urls(source_entity)
else:
self.urls = []
--- a/cubicweb/server/sources/ldapfeed.py Wed Apr 12 16:07:25 2017 +0200
+++ b/cubicweb/server/sources/ldapfeed.py Wed Apr 12 16:10:57 2017 +0200
@@ -176,18 +176,23 @@
_conn = None
+ def check_urls(self, source_entity):
+ urls = super(LDAPFeedSource, self).check_urls(source_entity)
+
+ if len(urls) > 1:
+ raise ValidationError(source_entity.eid, {'url': _('can only have one url')})
+
+ try:
+ protocol, hostport = urls[0].split('://')
+ except ValueError:
+ raise ValidationError(source_entity.eid, {'url': _('badly formatted url')})
+ if protocol not in PROTO_PORT:
+ raise ValidationError(source_entity.eid, {'url': _('unsupported protocol')})
+
+ return urls
+
def init(self, source_entity):
super(LDAPFeedSource, self).init(source_entity)
- if self.urls:
- if len(self.urls) > 1:
- raise ValidationError(source_entity.eid, {'url': _('can only have one url')})
- try:
- protocol, hostport = self.urls[0].split('://')
- except ValueError:
- raise ValidationError(source_entity.eid, {'url': _('badly formatted url')})
- if protocol not in PROTO_PORT:
- raise ValidationError(source_entity.eid, {'url': _('unsupported protocol')})
-
typedconfig = self.config
self.authmode = typedconfig['auth-mode']
self._authenticate = getattr(self, '_auth_%s' % self.authmode)
--- a/cubicweb/server/sources/native.py Wed Apr 12 16:07:25 2017 +0200
+++ b/cubicweb/server/sources/native.py Wed Apr 12 16:10:57 2017 +0200
@@ -355,6 +355,12 @@
"the 'sources' file, not in the database")
raise ValidationError(source_entity.eid, {role_name('config', 'subject'): msg})
+ def check_urls(self, source_entity):
+ if source_entity.url:
+ msg = _("Configuration of the system source goes to "
+ "the 'sources' file, not in the database")
+ raise ValidationError(source_entity.eid, {role_name('config', 'subject'): msg})
+
def add_authentifier(self, authentifier):
self.authentifiers.append(authentifier)
authentifier.source = self
--- a/cubicweb/server/test/unittest_datafeed.py Wed Apr 12 16:07:25 2017 +0200
+++ b/cubicweb/server/test/unittest_datafeed.py Wed Apr 12 16:10:57 2017 +0200
@@ -149,6 +149,15 @@
with self.assertRaises(ValidationError) as cm:
cnx.create_entity(
'CWSource', name=u'error', type=u'datafeed', parser=u'testparser',
+ url=None,
+ config=u'synchronization-interval=1min')
+ self.assertIn('specifying an URL is mandatory',
+ str(cm.exception))
+ cnx.rollback()
+
+ with self.assertRaises(ValidationError) as cm:
+ cnx.create_entity(
+ 'CWSource', name=u'error', type=u'datafeed', parser=u'testparser',
url=u'ignored',
config=u'synch-interval=1min')
self.assertIn('unknown options synch-interval',
--- a/cubicweb/server/test/unittest_ldapsource.py Wed Apr 12 16:07:25 2017 +0200
+++ b/cubicweb/server/test/unittest_ldapsource.py Wed Apr 12 16:10:57 2017 +0200
@@ -34,7 +34,7 @@
from six import string_types
from six.moves import range
-from cubicweb import AuthenticationError
+from cubicweb import AuthenticationError, ValidationError
from cubicweb.devtools.testlib import CubicWebTC
from cubicweb.devtools.httptest import get_available_port
@@ -307,6 +307,33 @@
self.assertIsNotNone(pwd)
self.assertTrue(str(pwd))
+ def test_bad_config(self):
+ with self.admin_access.cnx() as cnx:
+
+ with self.assertRaises(ValidationError) as cm:
+ cnx.create_entity(
+ 'CWSource', name=u'erroneous', type=u'ldapfeed', parser=u'ldapfeed',
+ url=u'ldap.com', config=CONFIG_LDAPFEED)
+ self.assertIn('badly formatted url',
+ str(cm.exception))
+ cnx.rollback()
+
+ with self.assertRaises(ValidationError) as cm:
+ cnx.create_entity(
+ 'CWSource', name=u'erroneous', type=u'ldapfeed', parser=u'ldapfeed',
+ url=u'http://ldap.com', config=CONFIG_LDAPFEED)
+ self.assertIn('unsupported protocol',
+ str(cm.exception))
+ cnx.rollback()
+
+ with self.assertRaises(ValidationError) as cm:
+ cnx.create_entity(
+ 'CWSource', name=u'erroneous', type=u'ldapfeed', parser=u'ldapfeed',
+ url=u'ldap://host1\nldap://host2', config=CONFIG_LDAPFEED)
+ self.assertIn('can only have one url',
+ str(cm.exception))
+ cnx.rollback()
+
class LDAPGeneratePwdTC(LDAPFeedTestBase):
"""
--- a/cubicweb/web/test/unittest_views_cwsources.py Wed Apr 12 16:07:25 2017 +0200
+++ b/cubicweb/web/test/unittest_views_cwsources.py Wed Apr 12 16:10:57 2017 +0200
@@ -35,7 +35,7 @@
with self.temporary_appobjects(AParser):
source = req.create_entity('CWSource', name=u'ext', type=u'datafeed',
- parser=u'cw.entityxml')
+ parser=u'cw.entityxml', url=u'whatever')
req.cnx.commit()
self.threads = 0