Maybe you're logged in Keycloak but still not in Plone. You should do the event notification later, in another PAS plugin maybe?
@yurj You're right, thanks for this tip, the callback
view has not yet logged in the user within Plone, it has only logged in the user in Keycloak.
Here I show a very debugging session to detect as the proper context to access the member
object
to invoke my user_logged_in_first
event handler.
When I log in using the /login
URL with the anapoleo
user, The UserInitialLoginInEvent
event is automatically fired,
because it is the first time that the user logs in:
2024-04-09 02:49:52,616 INFO [collective.fingerpointing:75][waitress-1] user=anapoleo ip=127.0.0.1 action=login
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(73)user_logged_in_first()
72 import ipdb ; ipdb.set_trace()
---> 73 portal = api.portal.get()
74 request = getattr(portal, "REQUEST", None)
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(74)user_logged_in_first()
73 portal = api.portal.get()
---> 74 request = getattr(portal, "REQUEST", None)
75 user_folder_id = api.portal.get_registry_record(
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(76)user_logged_in_first()
75 request = getattr(portal, "REQUEST", None)
---> 76 user_folder_id = api.portal.get_registry_record(
77 "user_folder_id", ICommunitySettings
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(77)user_logged_in_first()
76 user_folder_id = api.portal.get_registry_record(
---> 77 "user_folder_id", ICommunitySettings
78 )
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(76)user_logged_in_first()
75 request = getattr(portal, "REQUEST", None)
---> 76 user_folder_id = api.portal.get_registry_record(
77 "user_folder_id", ICommunitySettings
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(80)user_logged_in_first()
79
---> 80 if not ILayer.providedBy(request):
81 return
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(83)user_logged_in_first()
82
---> 83 with api.env.adopt_roles(roles=["Manager"]):
84
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(86)user_logged_in_first()
85 # Plone User Folder
---> 86 if user_folder_id not in portal.objectIds():
87 uf = api.content.create(
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(95)user_logged_in_first()
94 else:
---> 95 LOG.info(f"The Plone User Folder '{user_folder_id}' exists as a content type!")
96 uf = portal[user_folder_id]
ipdb>
2024-04-09 02:50:11,251 INFO [my.package:95][waitress-1] The Plone User Folder 'users' exists as a content type!
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(96)user_logged_in_first()
95 LOG.info(f"The Plone User Folder '{user_folder_id}' exists as a content type!")
---> 96 uf = portal[user_folder_id]
97
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(99)user_logged_in_first()
98 # Plone User
---> 99 user = api.user.get_current()
100 user_id = user.getId()
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(100)user_logged_in_first()
99 user = api.user.get_current()
--> 100 user_id = user.getId()
101 plone_user_obj = None
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(101)user_logged_in_first()
100 user_id = user.getId()
--> 101 plone_user_obj = None
102
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(103)user_logged_in_first()
102
--> 103 if user_id not in uf.objectIds():
104 try:
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(104)user_logged_in_first()
103 if user_id not in uf.objectIds():
--> 104 try:
105 plone_user_obj = api.content.create(
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(105)user_logged_in_first()
104 try:
--> 105 plone_user_obj = api.content.create(
106 type="PloneUser",
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(106)user_logged_in_first()
105 plone_user_obj = api.content.create(
--> 106 type="PloneUser",
107 id=user_id or "john.doe",
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(107)user_logged_in_first()
106 type="PloneUser",
--> 107 id=user_id or "john.doe",
108 title=user_id or "John Doe",
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(108)user_logged_in_first()
107 id=user_id or "john.doe",
--> 108 title=user_id or "John Doe",
109 container=uf,
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(109)user_logged_in_first()
108 title=user_id or "John Doe",
--> 109 container=uf,
110 email=user.getProperty('email') or "john.doe@mail.com",
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(110)user_logged_in_first()
109 container=uf,
--> 110 email=user.getProperty('email') or "john.doe@mail.com",
111 accept=user.getProperty('accept') or True,
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(111)user_logged_in_first()
110 email=user.getProperty('email') or "john.doe@mail.com",
--> 111 accept=user.getProperty('accept') or True,
112 newsletter=user.getProperty('newsletter') or False
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(112)user_logged_in_first()
111 accept=user.getProperty('accept') or True,
--> 112 newsletter=user.getProperty('newsletter') or False
113 )
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(105)user_logged_in_first()
104 try:
--> 105 plone_user_obj = api.content.create(
106 type="PloneUser",
ipdb>
2024-04-09 02:50:18,851 INFO [collective.fingerpointing:75][waitress-1] user=anapoleo ip=127.0.0.1 action=create object=<PloneUser at /my/users/anapoleo>
2024-04-09 02:50:19,108 INFO [collective.fingerpointing:75][waitress-1] user=anapoleo ip=127.0.0.1 action=modify object=<PloneUserFolder at /my/users>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(114)user_logged_in_first()
113 )
--> 114 api.portal.show_message(
115 "Your account has been created.", request
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(115)user_logged_in_first()
114 api.portal.show_message(
--> 115 "Your account has been created.", request
116 )
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(114)user_logged_in_first()
113 )
--> 114 api.portal.show_message(
115 "Your account has been created.", request
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(117)user_logged_in_first()
116 )
--> 117 LOG.info(f"The Plone User '{plone_user_obj.getId()}' was created as a content type!")
118 except InvalidParameterError as err:
ipdb> n
2024-04-09 02:50:29,275 INFO [my.package:117][waitress-1] The Plone User 'anapoleo' was created as a content type!
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(134)user_logged_in_first()
133
--> 134 import ipdb ; ipdb.set_trace()
135 # Grant the role 'Member' to user logged in
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(136)user_logged_in_first()
135 # Grant the role 'Member' to user logged in
--> 136 roles = api.user.get_roles(username=user_id)
137 if not "Member" in roles:
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(137)user_logged_in_first()
136 roles = api.user.get_roles(username=user_id)
--> 137 if not "Member" in roles:
138 try:
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(156)user_logged_in_first()
155 else:
--> 156 LOG.info(f"The '{user_id}' object has the role 'Member'!")
157
ipdb>
2024-04-09 02:50:52,644 INFO [my.package:156][waitress-1] The 'anapoleo' object has the role 'Member'!
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(158)user_logged_in_first()
157
--> 158 import ipdb ; ipdb.set_trace()
159 # User logged in the first time?
ipdb>
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(160)user_logged_in_first()
159 # User logged in the first time?
--> 160 if user_id in uf.objectIds():
161 if not plone_user_obj.first_login:
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(161)user_logged_in_first()
160 if user_id in uf.objectIds():
--> 161 if not plone_user_obj.first_login:
162 plone_user_obj.first_login = datetime.now(timezone.utc)
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(162)user_logged_in_first()
161 if not plone_user_obj.first_login:
--> 162 plone_user_obj.first_login = datetime.now(timezone.utc)
163 plone_user_obj.last_login = datetime.now(timezone.utc)
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(163)user_logged_in_first()
162 plone_user_obj.first_login = datetime.now(timezone.utc)
--> 163 plone_user_obj.last_login = datetime.now(timezone.utc)
164 LOG.info(f"The 'first_login' and 'last_login' properties of '{plone_user_obj.getId()}' object were updated!")
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(164)user_logged_in_first()
163 plone_user_obj.last_login = datetime.now(timezone.utc)
--> 164 LOG.info(f"The 'first_login' and 'last_login' properties of '{plone_user_obj.getId()}' object were updated!")
165
ipdb> n
2024-04-09 02:51:08,283 INFO [my.package:164][waitress-1] The 'first_login' and 'last_login' properties of 'anapoleo' object were updated!
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(166)user_logged_in_first()
165
--> 166 redirect_after_registration = api.portal.get_registry_record(
167 "redirect_after_registration", ICommunitySettings
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(167)user_logged_in_first()
166 redirect_after_registration = api.portal.get_registry_record(
--> 167 "redirect_after_registration", ICommunitySettings
168 )
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(166)user_logged_in_first()
165
--> 166 redirect_after_registration = api.portal.get_registry_record(
167 "redirect_after_registration", ICommunitySettings
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(169)user_logged_in_first()
168 )
--> 169 if redirect_after_registration:
170 return plone_user_obj.absolute_url()
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(170)user_logged_in_first()
169 if redirect_after_registration:
--> 170 return plone_user_obj.absolute_url()
171
ipdb> n
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(83)user_logged_in_first()
82
---> 83 with api.env.adopt_roles(roles=["Manager"]):
84
ipdb> n
--Return--
'http://local...sers/anapoleo'
> /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/handlers.py(83)user_logged_in_first()
82
---> 83 with api.env.adopt_roles(roles=["Manager"]):
84
Next, continue the user authentication workflow within Plone:
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/zope.interface-6.0-py3.11-linux-x86_64.egg/zope/interface/adapter.py(895)subscribers()
894 result = ()
--> 895 for subscription in subscriptions:
896 subscription(*objects)
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/zope.interface-6.0-py3.11-linux-x86_64.egg/zope/interface/adapter.py(903)subscribers()
902 result.append(subscriber)
--> 903 return result
904
ipdb>
--Return--
()
> /home/macagua/projects/plone-6.0.7/eggs/cp311/zope.interface-6.0-py3.11-linux-x86_64.egg/zope/interface/adapter.py(903)subscribers()
902 result.append(subscriber)
--> 903 return result
904
ipdb>
--Return--
()
> /home/macagua/projects/plone-6.0.7/eggs/cp311/zope.interface-6.0-py3.11-linux-x86_64.egg/zope/interface/registry.py(445)subscribers()
444 def subscribers(self, objects, provided):
--> 445 return self.adapters.subscribers(objects, provided)
446
ipdb>
--Return--
()
> /home/macagua/projects/plone-6.0.7/eggs/cp311/zope.component-6.0-py3.11.egg/zope/component/_api.py(146)subscribers()
145 return []
--> 146 return sitemanager.subscribers(objects, interface)
147
ipdb>
--Return--
None
> /home/macagua/projects/plone-6.0.7/eggs/cp311/zope.component-6.0-py3.11.egg/zope/component/event.py(27)dispatch()
26 def dispatch(*event):
---> 27 component_subscribers(event, None)
28
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/zope.event-5.0-py3.11.egg/zope/event/__init__.py(32)notify()
31 """
---> 32 for subscriber in subscribers:
33 subscriber(event)
ipdb>
--Return--
None
> /home/macagua/projects/plone-6.0.7/eggs/cp311/zope.event-5.0-py3.11.egg/zope/event/__init__.py(32)notify()
31 """
---> 32 for subscriber in subscribers:
33 subscriber(event)
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.PlonePAS-8.0.2-py3.11.egg/Products/PlonePAS/tools/membership.py(662)loginUser()
661
--> 662 if REQUEST is None:
663 REQUEST = getattr(self, "REQUEST", None)
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.PlonePAS-8.0.2-py3.11.egg/Products/PlonePAS/tools/membership.py(664)loginUser()
663 REQUEST = getattr(self, "REQUEST", None)
--> 664 if REQUEST is None:
665 return
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.PlonePAS-8.0.2-py3.11.egg/Products/PlonePAS/tools/membership.py(668)loginUser()
667 # Expire the clipboard
--> 668 if REQUEST.get("__cp", None) is not None:
669 REQUEST.RESPONSE.expireCookie("__cp", path="/")
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.PlonePAS-8.0.2-py3.11.egg/Products/PlonePAS/tools/membership.py(671)loginUser()
670
--> 671 self.createMemberArea()
672
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.PlonePAS-8.0.2-py3.11.egg/Products/PlonePAS/tools/membership.py(673)loginUser()
672
--> 673 try:
674 pas = getToolByName(self, "acl_users")
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.PlonePAS-8.0.2-py3.11.egg/Products/PlonePAS/tools/membership.py(674)loginUser()
673 try:
--> 674 pas = getToolByName(self, "acl_users")
675 pas.credentials_cookie_auth.login()
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.PlonePAS-8.0.2-py3.11.egg/Products/PlonePAS/tools/membership.py(675)loginUser()
674 pas = getToolByName(self, "acl_users")
--> 675 pas.credentials_cookie_auth.login()
676 except AttributeError:
ipdb> locals()
{'self': <MembershipTool at /Plone/portal_membership>, 'REQUEST': <WSGIRequest, URL=http://localhost:7080/my/login>, 'user': <PloneUser 'anapoleo'>, 'pas': <PluggableAuthService at /my/acl_users>}
ipdb> user.__dir__()
['_id', '_login', '_propertysheets', '_groups', '_roles', '__module__', '_isGroup', '__init__', '_getPAS', '_getPlugins',
'isGroup', 'getName', 'getUserId', 'getGroupNames', 'getGroupIds', 'getPropertysheet', 'addPropertysheet', '_getPropertyPlugins',
'getOrderedPropertySheets', '_getLocalRolesPlugins', 'getRolesInContext', 'allowed', 'setProperties', 'getProperty', 'isGroup__roles__',
'getName__roles__', 'getUserId__roles__', 'getGroupNames__roles__', 'getGroupIds__roles__', 'getPropertysheet__roles__',
'addPropertysheet__roles__', 'getOrderedPropertySheets__roles__', '__ac_permissions__', '__implemented__', '__provides__', '__doc__',
'getId', 'getUserName', 'getRoles', 'getGroups', 'getDomains', '_addGroups', '_addRoles', 'listPropertysheets', '__getitem__',
'zmi_icon', '__allow_access_to_unprotected_subobjects__', '_getPassword', 'authenticate', '_check_context', 'domains', 'has_role',
'has_permission', '__len__', '__str__', '__repr__', '__dict__', '__weakref__', '__providedBy__', '__new__', '__of__', '__getattribute__',
'__getstate__', '__setstate__', '__reduce__', '__hash__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__',
'__ge__', '__reduce_ex__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
ipdb> user.getId()
'anapoleo'
ipdb> user.getUserName()
'anapoleo'
ipdb> n
--Return--
None
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.PlonePAS-8.0.2-py3.11.egg/Products/PlonePAS/tools/membership.py(675)loginUser()
674 pas = getToolByName(self, "acl_users")
--> 675 pas.credentials_cookie_auth.login()
676 except AttributeError:
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(144)_post_login()
143 membership_tool.loginUser(self.request)
--> 144 if is_initial_login:
145 self.handle_initial_login()
ipdb> locals()
{'self': <Products.Five.browser.metaconfigure.SimpleViewClass from /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/browser/login/templates/login.pt object at 0x7f90ef78c4d0>, 'membership_tool': <MembershipTool at /Plone/portal_membership>, 'member': <Products.PlonePAS.tools.memberdata.MemberData object at 0x7f90efb8a750>, 'must_change_password': 0, 'login_time': DateTime('2000/01/01 00:00:00 GMT-4'), 'is_initial_login': True}
ipdb> member.__dir__()
['_user', '_tool', '__parent__', '_md', 'id', '__module__', '__init__', 'setMemberProperties', 'getProperty', 'hasProperty',
'getPassword', 'canDelete', 'canPasswordSet', 'passwordInClear', '_memberdataHasProperty', 'canWriteProperty', 'canAddToGroup',
'canRemoveFromGroup', 'canAssignRole', 'setSecurityProfile', '_getPlugins', 'has_permission', 'getGroups', 'getUserId', '__doc__',
'__component_adapts__', '__implemented__', '__provides__', 'hasProperty__roles__', 'setSecurityProfile__roles__', '_getPlugins__roles__',
'has_permission__roles__', 'getGroups__roles__', 'getUserId__roles__', '__ac_permissions__', 'notifyModified', 'getUser', 'getMemberId',
'setProperties', '__str__', 'getId', 'getUserName', 'getRoles', 'getRolesInContext', 'getDomains', 'has_role', '__dict__', '__weakref__',
'__providedBy__', 'notifyModified__roles__', 'getUser__roles__', 'getMemberId__roles__', 'setMemberProperties__roles__',
'getProperty__roles__', 'getPassword__roles__', 'getId__roles__', 'getUserName__roles__', 'getRoles__roles__', 'getRolesInContext__roles__',
'getDomains__roles__', 'has_role__roles__', 'setProperties__roles__', '__new__', '__repr__', '__hash__', '__getattribute__', '__setattr__',
'__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__reduce_ex__', '__reduce__', '__getstate__', '__subclasshook__',
'__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
ipdb> member.getId()
'anapoleo'
ipdb> member.getUserName()
'anapoleo'
ipdb> member.getRoles()
['Member', 'Authenticated']
ipdb> member.hasProperty('email')
True
In the _post_login()
method into LoginForm
class from the Products.CMFPlone.browser.login.login.py
module, here the right
context to access all the member data needs to fire my event handler with the right data session because here the Keycloak user is logged
in into Plone.
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(145)_post_login()
144 if is_initial_login:
--> 145 self.handle_initial_login()
146
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(147)_post_login()
146
--> 147 if must_change_password:
148 self.force_password_change()
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(149)_post_login()
148 self.force_password_change()
--> 149 return is_initial_login
150
ipdb>
--Return--
True
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(149)_post_login()
148 self.force_password_change()
--> 149 return is_initial_login
150
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(180)handleLogin()
179 is_initial_login = self._post_login()
--> 180 status_msg.addStatusMessage(
181 _(
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(181)handleLogin()
180 status_msg.addStatusMessage(
--> 181 _(
182 "you_are_now_logged_in",
ipdb> locals()
{'self': <Products.Five.browser.metaconfigure.SimpleViewClass from /home/macagua/projects/plone-6.0.7/src/my.package/src/my/package/browser/login/templates/login.pt object at 0x7f90ef78c4d0>,
'action': <ButtonAction 'buttons.login' 'Log in'>, 'data': {'ac_name': 'anapoleo', 'ac_password': 'anapoleo123', 'came_from': 'http://localhost:7080/Plone'}, 'errors': (), 'membership_tool': <MembershipTool at /Plone/portal_membership>, 'status_msg': <Products.statusmessages.adapter.StatusMessage object at 0x7f90ef34e310>, 'is_initial_login': True}
ipdb> data['ac_name']
'anapoleo'
ipdb> data['ac_password']
'anapoleo123'
ipdb> membership_tool.getAuthenticatedMember()
<Products.PlonePAS.tools.memberdata.MemberData object at 0x7f90ee7db710>
ipdb> authenticated_member = membership_tool.getAuthenticatedMember()
ipdb> authenticated_member.getUserName()
'anapoleo'
ipdb> authenticated_member.getUser()
<PloneUser 'anapoleo'>
ipdb> authenticated_member.getId()
'anapoleo'
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(182)handleLogin()
181 _(
--> 182 "you_are_now_logged_in",
183 default="Welcome! You are now logged in.",
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(183)handleLogin()
182 "you_are_now_logged_in",
--> 183 default="Welcome! You are now logged in.",
184 ),
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(181)handleLogin()
180 status_msg.addStatusMessage(
--> 181 _(
182 "you_are_now_logged_in",
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(185)handleLogin()
184 ),
--> 185 "info",
186 )
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(180)handleLogin()
179 is_initial_login = self._post_login()
--> 180 status_msg.addStatusMessage(
181 _(
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(188)handleLogin()
187
--> 188 came_from = data.get("came_from", None)
189 self.redirect_after_login(came_from, is_initial_login)
ipdb>
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(189)handleLogin()
188 came_from = data.get("came_from", None)
--> 189 self.redirect_after_login(came_from, is_initial_login)
190
ipdb>
--Return--
None
> /home/macagua/projects/plone-6.0.7/eggs/cp311/Products.CMFPlone-6.0.7-py3.11.egg/Products/CMFPlone/browser/login/login.py(189)handleLogin()
188 came_from = data.get("came_from", None)
--> 189 self.redirect_after_login(came_from, is_initial_login)
190
ipdb>
--Return--
None
> /home/macagua/projects/plone-6.0.7/eggs/cp311/z3c.form-4.3-py3.11.egg/z3c/form/button.py(159)__call__()
158 def __call__(self, form, action):
--> 159 return self.func(form, action)
160
ipdb> n
--Return--
None
> /home/macagua/projects/plone-6.0.7/eggs/cp311/z3c.form-4.3-py3.11.egg/z3c/form/button.py(301)__call__()
299 if handler is None:
300 return
--> 301 return handler(self.form, self.action)
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/z3c.form-4.3-py3.11.egg/z3c/form/action.py(102)execute()
101 else:
--> 102 zope.event.notify(ActionSuccessful(action))
103 return result
ipdb> n
> /home/macagua/projects/plone-6.0.7/eggs/cp311/z3c.form-4.3-py3.11.egg/z3c/form/action.py(103)execute()
102 zope.event.notify(ActionSuccessful(action))
--> 103 return result
104
ipdb> c
2024-04-09 03:05:30,017 INFO [collective.fingerpointing:75][waitress-0] user=anapoleo ip=127.0.0.1 action=modify object=<PloneUser at /my/users/anapoleo>
2024-04-09 03:05:34,592 INFO [collective.fingerpointing:75][waitress-1] user=anapoleo ip=127.0.0.1 action=logout
My question is: is there possible to override the _post_login()
method into LoginForm
class from the
Products.CMFPlone.browser.login.login.py
module?
I added a new my/package/browser/login.py
file with the following content:
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.browser.login.login import LoginForm as BaseLoginForm
from Products.CMFPlone.browser.login.utils import has_logged_in
from Products.PlonePAS.events import UserInitialLoginInEvent
from zope.event import notify
from my.package.logger import LOG
class CustomLoginForm(BaseLoginForm):
"""An Override Implementation of the login form class
Args:
LoginForm (cls): Login Form Class
"""
def _post_login(self):
membership_tool = getToolByName(self.context, "portal_membership")
member = membership_tool.getAuthenticatedMember()
must_change_password = member.getProperty("must_change_password", 0)
login_time = member.getProperty("login_time", None)
is_initial_login = not has_logged_in(login_time)
membership_tool.loginUser(self.request)
if is_initial_login:
try:
# Create the event instance
event = UserInitialLoginInEvent(member)
# Notify the system
notify(event)
except Exception as e:
LOG.error(e)
self.handle_initial_login()
if must_change_password:
self.force_password_change()
return is_initial_login
def __call__(self):
"""custom __call__ method"""
import ipdb ; ipdb.set_trace()
self._post_login()
try:
return super().__call__()
except Exception as e:
LOG.info("There was an error handling the login process")
LOG.error(e)
self.request.response.setHeader(
"Cache-Control", "no-cache, must-revalidate"
)
return self.request.response.redirect("/")
I added into the my/package/browser/configure.zcml
file the new entry:
<!-- Login Form -->
<browser:page
for="plone.base.interfaces.ILoginForm"
name="login"
class="my.package.browser.login.CustomLoginForm"
layer="my.package.interfaces.ILayer"
permission="zope2.View"
/>
Next stop and start the Zope instance, reinstall my.package
addon, and try to log in from the
/acl_users/oidc/login
URL with an External user from Keycloak, the CustomLoginForm
class is omitted
because my breakpoint into __callback__
method is not fired.
How override the _post_login method with my code?
I think you want to use override.zcml. But you can also use z3c.jbot to override things in your package. My question is how PAS knows about CMFPlone/browser/login/login.py
? Maybe you can just add a plugin to manage the login as Plone does? I'm not a PAS expert so I don't really know.