From ee4f778b022102ff7562622559d323c090431059 Mon Sep 17 00:00:00 2001 From: ezvirtual Date: Thu, 29 Mar 2018 16:20:03 +1300 Subject: [PATCH 1/5] trigger PropertiesUpdated event when user properties are updated add simple test for properties updated event make test imports consistent with existing style & re-order --- CHANGES.rst | 1 + setup.py | 2 ++ .../PlonePAS/tests/test_memberdatatool.py | 19 +++++++++++++++++++ src/Products/PlonePAS/tools/memberdata.py | 7 +++++++ 4 files changed, 29 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 9c9fd9a7..476b7d20 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,7 @@ Changelog .. towncrier release notes start + 6.0.2 (2019-04-29) ------------------ diff --git a/setup.py b/setup.py index 13c9ad16..9328cef8 100644 --- a/setup.py +++ b/setup.py @@ -3,8 +3,10 @@ from setuptools import find_packages import sys + version = '6.0.3.dev0' + longdescription = open("README.rst").read() longdescription += '\n' longdescription += open("CHANGES.rst").read() diff --git a/src/Products/PlonePAS/tests/test_memberdatatool.py b/src/Products/PlonePAS/tests/test_memberdatatool.py index 89ba2267..b5220342 100644 --- a/src/Products/PlonePAS/tests/test_memberdatatool.py +++ b/src/Products/PlonePAS/tests/test_memberdatatool.py @@ -4,12 +4,17 @@ from plone.app.testing import TEST_USER_ID as default_user from Products.PlonePAS.tests import dummy from Products.PlonePAS.testing import PRODUCTS_PLONEPAS_INTEGRATION_TESTING +from zope.component import getGlobalSiteManager from zope.component import getMultiAdapter from Products.CMFCore.interfaces import IMember +from Products.CMFCore.interfaces import IMemberData +from Products.PluggableAuthService.interfaces.events import \ + IPropertiesUpdatedEvent import unittest + class TestMemberDataTool(unittest.TestCase): layer = PRODUCTS_PLONEPAS_INTEGRATION_TESTING @@ -88,3 +93,17 @@ def testMemberDataAdapter(self): wrapped_user = self.memberdata.wrapUser(member) self.assertEqual(wrapped_user.__class__, MemberData) + + def testPropertiesUpdatedEvent(self): + + def event_handler(context, event): + self._properties_updated_handler_called = True + + gsm = zope.component.getGlobalSiteManager() + gsm.registerHandler(event_handler, + (IMemberData, IPropertiesUpdatedEvent)) + + self._properties_updated_handler_called = False + self.addMember('ez', 'Ez Zy', 'ez@ezmail.net', + ['Member'], '2018-01-01') + self.assertTrue(self._properties_updated_handler_called) diff --git a/src/Products/PlonePAS/tools/memberdata.py b/src/Products/PlonePAS/tools/memberdata.py index 063f25bd..a3a7c413 100644 --- a/src/Products/PlonePAS/tools/memberdata.py +++ b/src/Products/PlonePAS/tools/memberdata.py @@ -19,12 +19,14 @@ from Products.PlonePAS.interfaces.memberdata import IMemberDataTool from Products.PlonePAS.interfaces.plugins import IUserManagement from Products.PlonePAS.interfaces.propertysheets import IMutablePropertySheet +from Products.PluggableAuthService.events import PropertiesUpdated from Products.PluggableAuthService.interfaces.authservice import \ IPluggableAuthService from Products.PluggableAuthService.interfaces.plugins import IPropertiesPlugin from Products.PluggableAuthService.interfaces.plugins import \ IRoleAssignerPlugin from zope.component import adapter +from zope.event import notify from zope.interface import implementer import six @@ -275,6 +277,11 @@ def setMemberProperties(self, mapping, force_local=0, force_empty=False): if modified: self.notifyModified() + # Trigger PropertiesUpdated event when member properties are updated, + # excluding user login events + if set(mapping.keys()) != set(('login_time', 'last_login_time')): + notify(PropertiesUpdated(self, mapping)) + def getProperty(self, id, default=_marker): """PAS-specific method to fetch a user's properties. Looks through the ordered property sheets. From 3ebea02a19e62008af5c5b2d63ab2746a30db7a4 Mon Sep 17 00:00:00 2001 From: ezvirtual Date: Tue, 24 Apr 2018 16:15:36 +1200 Subject: [PATCH 2/5] Changes to notify(PropertiesUpdated) event & tests based on pull-request feedback --- .../PlonePAS/tests/test_memberdatatool.py | 39 ++++++++++++++++++- src/Products/PlonePAS/tools/memberdata.py | 2 +- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/Products/PlonePAS/tests/test_memberdatatool.py b/src/Products/PlonePAS/tests/test_memberdatatool.py index b5220342..c00acd98 100644 --- a/src/Products/PlonePAS/tests/test_memberdatatool.py +++ b/src/Products/PlonePAS/tests/test_memberdatatool.py @@ -104,6 +104,41 @@ def event_handler(context, event): (IMemberData, IPropertiesUpdatedEvent)) self._properties_updated_handler_called = False - self.addMember('ez', 'Ez Zy', 'ez@ezmail.net', - ['Member'], '2018-01-01') + + username = 'ez' + roles = ['Member'] + fullname = 'Ez Zy' + email = 'ez@ezmail.net' + + self.membership.addMember(username, 'secret', roles, []) + member = self.membership.getMemberById(username) + + self.assertFalse(self._properties_updated_handler_called) + + member.setMemberProperties({ + 'fullname': fullname, + 'email': email}) + self.assertTrue(self._properties_updated_handler_called) + + # Test that notify(PropertiesUpdated) isn't called on user login. + self._properties_updated_handler_called = False + login(self.portal, username) + # Imitate a login as the plone.app.testing login method doesn't seem to + # set these member properties. + member.setMemberProperties({ + 'login_time': DateTime('2018-02-15'), + 'last_login_time': DateTime('2018-02-15')}) + + self.assertFalse(self._properties_updated_handler_called) + + # Test notify(PropertiesUpdated) isn't called when login_time is + # present as we're assuming this should only be changed on login. + self._properties_updated_handler_called = False + member.setMemberProperties({ + 'login_time': DateTime('2018-02-15'), + 'fullname': 'Bed Rock'}) + + self.assertFalse(self._properties_updated_handler_called) + gsm.unregisterHandler(event_handler, + (IMemberData, IPropertiesUpdatedEvent)) diff --git a/src/Products/PlonePAS/tools/memberdata.py b/src/Products/PlonePAS/tools/memberdata.py index a3a7c413..361844e7 100644 --- a/src/Products/PlonePAS/tools/memberdata.py +++ b/src/Products/PlonePAS/tools/memberdata.py @@ -279,7 +279,7 @@ def setMemberProperties(self, mapping, force_local=0, force_empty=False): # Trigger PropertiesUpdated event when member properties are updated, # excluding user login events - if set(mapping.keys()) != set(('login_time', 'last_login_time')): + if not set(mapping.keys()) & set(('login_time', 'last_login_time')): notify(PropertiesUpdated(self, mapping)) def getProperty(self, id, default=_marker): From 6ff44ecc5466831618c30dce6d748669a263ad3d Mon Sep 17 00:00:00 2001 From: ezvirtual Date: Tue, 24 Apr 2018 17:27:55 +1200 Subject: [PATCH 3/5] remove login call from test as it doesn't seem to set login_time or last_login_time properties that I'm attempting to test --- src/Products/PlonePAS/tests/test_memberdatatool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Products/PlonePAS/tests/test_memberdatatool.py b/src/Products/PlonePAS/tests/test_memberdatatool.py index c00acd98..8a0c5d85 100644 --- a/src/Products/PlonePAS/tests/test_memberdatatool.py +++ b/src/Products/PlonePAS/tests/test_memberdatatool.py @@ -123,7 +123,7 @@ def event_handler(context, event): # Test that notify(PropertiesUpdated) isn't called on user login. self._properties_updated_handler_called = False - login(self.portal, username) + # Imitate a login as the plone.app.testing login method doesn't seem to # set these member properties. member.setMemberProperties({ From 718555196fa48af6dc8e17f2691b4ee091edd9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Mon, 25 Nov 2019 23:55:13 +0100 Subject: [PATCH 4/5] Fix test --- src/Products/PlonePAS/tests/test_memberdatatool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Products/PlonePAS/tests/test_memberdatatool.py b/src/Products/PlonePAS/tests/test_memberdatatool.py index 8a0c5d85..6189d267 100644 --- a/src/Products/PlonePAS/tests/test_memberdatatool.py +++ b/src/Products/PlonePAS/tests/test_memberdatatool.py @@ -99,7 +99,7 @@ def testPropertiesUpdatedEvent(self): def event_handler(context, event): self._properties_updated_handler_called = True - gsm = zope.component.getGlobalSiteManager() + gsm = getGlobalSiteManager() gsm.registerHandler(event_handler, (IMemberData, IPropertiesUpdatedEvent)) From b8d6bbc58b43b8c0ff14f578451bd0a83740460d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Tue, 26 Nov 2019 00:02:43 +0100 Subject: [PATCH 5/5] Update changelog --- news/27.bugfix | 5 +++++ news/50.bugfix | 2 -- news/51.bugfix | 3 --- news/52.bugfix | 3 --- 4 files changed, 5 insertions(+), 8 deletions(-) create mode 100644 news/27.bugfix delete mode 100644 news/50.bugfix delete mode 100644 news/51.bugfix delete mode 100644 news/52.bugfix diff --git a/news/27.bugfix b/news/27.bugfix new file mode 100644 index 00000000..60c120aa --- /dev/null +++ b/news/27.bugfix @@ -0,0 +1,5 @@ +- Notify PropertiesUpdated event when member properties are changed + [ezvirtual] + +- Add simple test for PropertiesUpdated event + [ezvirtual] diff --git a/news/50.bugfix b/news/50.bugfix deleted file mode 100644 index 160e733e..00000000 --- a/news/50.bugfix +++ /dev/null @@ -1,2 +0,0 @@ -Log exception from PAS logout() instead of swallowing them -[ajung] diff --git a/news/51.bugfix b/news/51.bugfix deleted file mode 100644 index ff89e3bc..00000000 --- a/news/51.bugfix +++ /dev/null @@ -1,3 +0,0 @@ -Fix deprecated imports. -Fix buildout infrastructure for Plone 5.2. -[thet] diff --git a/news/52.bugfix b/news/52.bugfix deleted file mode 100644 index 9beaabf2..00000000 --- a/news/52.bugfix +++ /dev/null @@ -1,3 +0,0 @@ -Create the MemberData object from an adapter instead of directly instantiating it, as intended in Products.CMFCore.MemberDataTool. -This allows for better extensibility. -[thet]