--- a/.hgtags Wed May 22 11:34:08 2019 +0200
+++ b/.hgtags Fri May 24 16:29:14 2019 +0200
@@ -633,3 +633,4 @@
ee4ad63c91e5406e29f079f1f2d3774361798ac8 3.26.7
91f75319a726b523a09103540d3bc6872aaf2ae4 3.26.8
4d6909de765ac036ddef00b5853213fcae56d525 3.26.9
+74cc5de1ee6c578db401c89716fdc43b27624a04 3.26.10
--- a/cubicweb/crypto.py Wed May 22 11:34:08 2019 +0200
+++ b/cubicweb/crypto.py Fri May 24 16:29:14 2019 +0200
@@ -25,6 +25,8 @@
_CYPHERERS = {}
+
+
def _cypherer(seed):
if isinstance(seed, str):
seed = seed.encode('utf-8')
@@ -37,12 +39,13 @@
def encrypt(data, seed):
string = pickle.dumps(data)
- string = string + '*' * (8 - len(string) % 8)
+ string = string + b'*' * (8 - len(string) % 8)
string = b64encode(_cypherer(seed).encrypt(string))
- return str(string)
+ return string.decode('utf-8')
def decrypt(string, seed):
+ string = string.encode('utf-8')
# pickle ignores trailing characters so we do not need to strip them off
string = _cypherer(seed).decrypt(b64decode(string))
return pickle.loads(string)
--- a/cubicweb/dataimport/importer.py Wed May 22 11:34:08 2019 +0200
+++ b/cubicweb/dataimport/importer.py Fri May 24 16:29:14 2019 +0200
@@ -71,7 +71,10 @@
def use_extid_as_cwuri_filter(extentities):
for extentity in extentities:
if extentity.extid not in extid2eid:
- extentity.values.setdefault('cwuri', set([extentity.extid.decode('utf-8')]))
+ cwuri = extentity.extid
+ if isinstance(cwuri, bytes):
+ cwuri = cwuri.decode('utf-8')
+ extentity.values.setdefault('cwuri', set([cwuri]))
yield extentity
return use_extid_as_cwuri_filter
--- a/cubicweb/dataimport/test/unittest_importer.py Wed May 22 11:34:08 2019 +0200
+++ b/cubicweb/dataimport/test/unittest_importer.py Fri May 24 16:29:14 2019 +0200
@@ -196,6 +196,12 @@
personne.values.pop('cwuri')
list(set_cwuri((personne,)))
self.assertNotIn('cwuri', personne.values)
+ personne = ExtEntity('Personne', u'ééé', {})
+ mapping = {}
+ set_cwuri = use_extid_as_cwuri(mapping)
+ list(set_cwuri((personne,)))
+ self.assertIn('cwuri', personne.values)
+ self.assertEqual(personne.values['cwuri'], set([u'ééé']))
class DropExtraValuesTC(CubicWebTC):
--- a/cubicweb/server/test/unittest_ldapsource.py Wed May 22 11:34:08 2019 +0200
+++ b/cubicweb/server/test/unittest_ldapsource.py Fri May 24 16:29:14 2019 +0200
@@ -251,6 +251,33 @@
source.authenticate, cnx, 'syt', 'toto')
self.assertTrue(source.authenticate(cnx, 'syt', 'syt'))
+ def test_ldapfeed_insert_collision(self):
+ """
+ when a user computed login from ldapfeed collides with a CWUser
+ login the user MUST not be inserted, and message MUST be present
+ at error level regarding the collision for troubleshooting purpose.
+ We also check that in case the CWUser is skipped, the entity EmailAddress
+ is not modified.
+ If EmailAddress are not modified, CWGroup are not.
+ """
+ with self.admin_access.cnx() as cnx:
+ user = cnx.find('CWUser', login=u'syt').one()
+ user.cw_set(cw_source=cnx.find('CWSource', name=u'system').one())
+ with cnx.security_enabled(write=False):
+ user.cw_set(cwuri=u'http://testing.fr/cubicweb/{}'.format(user.eid))
+ for mail in user.use_email:
+ mail.cw_set(address=mail.address[:-3] + u".net")
+ cnx.commit()
+ with self.assertLogs('cubicweb.appobject', level='ERROR') as cm:
+ self.pull(cnx)
+ self.assertEqual(
+ cm.output,
+ ['ERROR:cubicweb.appobject:not synchronizing user syt.'
+ ' User already exist in source system']
+ )
+ for mail in user.use_email:
+ self.assertTrue(mail.address.endswith(".net"))
+
def test_base(self):
with self.admin_access.repo_cnx() as cnx:
# check a known one
--- a/cubicweb/sobjects/ldapparser.py Wed May 22 11:34:08 2019 +0200
+++ b/cubicweb/sobjects/ldapparser.py Fri May 24 16:29:14 2019 +0200
@@ -154,9 +154,26 @@
def extentities_generator(self):
self.debug('processing ldapfeed source %s %s', self.source, self.searchgroupfilterstr)
+ # get existing users *not* managed by this source
+ non_managed_users = dict(self._cw.execute(
+ 'Any L, SN WHERE'
+ ' U is CWUser, U login L,'
+ ' U cw_source S, S name SN,'
+ ' NOT S eid %(eid)s',
+ {'eid': self.source.eid}, build_descr=False))
# generate users and email addresses
for userdict in self.user_source_entities_by_extid.values():
attrs = self.ldap2cwattrs(userdict, 'CWUser')
+ login = attrs['login'][0]
+ try:
+ source = non_managed_users[login]
+ except KeyError:
+ pass
+ else:
+ self.error(
+ 'not synchronizing user %s. User already exist in source %s',
+ login, source)
+ continue
pwd = attrs.get('upassword')
if not pwd:
# generate a dumb password if not fetched from ldap (see
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cubicweb/test/unittest_crypto.py Fri May 24 16:29:14 2019 +0200
@@ -0,0 +1,18 @@
+from unittest import TestCase
+
+from cubicweb import crypto
+
+
+class CryptoTC(TestCase):
+
+ def test_encrypt_decrypt_roundtrip(self):
+ data = {'a': u'ah', 'b': [1, 2]}
+ seed = 'ssss'
+ crypted = crypto.encrypt(data, seed)
+ decrypted = crypto.decrypt(crypted, seed)
+ self.assertEqual(decrypted, data)
+
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
--- a/flake8-ok-files.txt Wed May 22 11:34:08 2019 +0200
+++ b/flake8-ok-files.txt Fri May 24 16:29:14 2019 +0200
@@ -3,6 +3,7 @@
cubicweb/_exceptions.py
cubicweb/cwctl.py
cubicweb/cwvreg.py
+cubicweb/crypto.py
cubicweb/dataimport/csv.py
cubicweb/dataimport/importer.py
cubicweb/dataimport/massive_store.py