# HG changeset patch # User Philippe Pepiot # Date 1558708154 -7200 # Node ID 32ee89340e590e07edd20c6811742f8e25c6dfdf # Parent 24b9073a661776e6636e4d23621c251c8dfb097c# Parent ba5231e1aa45614706e8675a5822eb874d230923 Merge 3.26 diff -r 24b9073a6617 -r 32ee89340e59 .hgtags --- 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 diff -r 24b9073a6617 -r 32ee89340e59 cubicweb/__pkginfo__.py diff -r 24b9073a6617 -r 32ee89340e59 cubicweb/crypto.py --- 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) diff -r 24b9073a6617 -r 32ee89340e59 cubicweb/dataimport/importer.py --- 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 diff -r 24b9073a6617 -r 32ee89340e59 cubicweb/dataimport/test/unittest_importer.py --- 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): diff -r 24b9073a6617 -r 32ee89340e59 cubicweb/server/test/unittest_ldapsource.py --- 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 diff -r 24b9073a6617 -r 32ee89340e59 cubicweb/sobjects/ldapparser.py --- 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 diff -r 24b9073a6617 -r 32ee89340e59 cubicweb/test/unittest_crypto.py --- /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() diff -r 24b9073a6617 -r 32ee89340e59 flake8-ok-files.txt --- 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 diff -r 24b9073a6617 -r 32ee89340e59 requirements/test-misc.txt