Skip to content

Commit

Permalink
Change login name after changing email in sites where "use email as l…
Browse files Browse the repository at this point in the history
…ogin" is enabled (#1836)

* add test case

* test case for managers changing password

* fix: changing email should change login name

* changelog

---------

Co-authored-by: Jens W. Klein <jk@kleinundpartner.at>
  • Loading branch information
erral and jensens authored Nov 8, 2024
1 parent 9f0feff commit 4f3bb4f
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 0 deletions.
2 changes: 2 additions & 0 deletions news/1835.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix log in after changing email when "email as login" is enabled
[erral]
9 changes: 9 additions & 0 deletions src/plone/restapi/services/users/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ def reply(self):
self.set_member_portrait(user, value)
user.setMemberProperties(mapping={key: value}, force_empty=True)

if security.use_email_as_login and "email" in user_settings_to_update:
value = user_settings_to_update["email"]
pas = getToolByName(self.context, "acl_users")
pas.updateLoginName(user.getId(), value)

roles = user_settings_to_update.get("roles", {})
if roles:
to_add = [key for key, enabled in roles.items() if enabled]
Expand Down Expand Up @@ -142,6 +147,10 @@ def reply(self):
self.set_member_portrait(user, value)
user.setMemberProperties(mapping={key: value}, force_empty=True)

if security.use_email_as_login and "email" in user_settings_to_update:
value = user_settings_to_update["email"]
set_own_login_name(user, value)

else:
if self._is_anonymous:
return self._error(
Expand Down
227 changes: 227 additions & 0 deletions src/plone/restapi/tests/test_services_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -1436,3 +1436,230 @@ def test_siteadm_not_change_manager_email(self):
self.assertEqual(
"manager@example.com", api.user.get(userid="manager").getProperty("email")
)

def test_manager_changes_email_when_login_with_email(self):
"""test that when login with email is enabled and a manager changes a user's email
they can log in with the new email
"""
# enable use_email_as_login
security_settings = getAdapter(self.portal, ISecuritySchema)
security_settings.use_email_as_login = True
transaction.commit()
# Create a user
response = self.api_session.post(
"/@users",
json={
"email": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(response.ok)
userid = response.json()["id"]

transaction.commit()
anon_response = self.anon_api_session.post(
"/@login",
json={
"login": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(anon_response.ok)

email_change_response = self.api_session.patch(
f"/@users/{userid}",
json={
"email": "new_email@example.com",
},
)
self.assertTrue(email_change_response.ok)
new_login_with_old_email_response = self.anon_api_session.post(
"/@login",
json={
"login": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertFalse(new_login_with_old_email_response.ok)
new_login_with_new_email_response = self.anon_api_session.post(
"/@login",
json={
"login": "new_email@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(new_login_with_new_email_response.ok)

def test_user_changes_email_when_login_with_email(self):
"""test that when login with email is enabled and the user changes their email
they can log in with the new email
"""
# enable use_email_as_login
security_settings = getAdapter(self.portal, ISecuritySchema)
security_settings.use_email_as_login = True
transaction.commit()
# Create a user
response = self.api_session.post(
"/@users",
json={
"email": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(response.ok)
userid = response.json()["id"]

transaction.commit()
anon_response = self.anon_api_session.post(
"/@login",
json={
"login": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(anon_response.ok)
auth_token = anon_response.json().get("token")

user_api_session = RelativeSession(self.portal_url, test=self)
user_api_session.headers.update({"Accept": "application/json"})
user_api_session.headers.update({"Authorization": f"Bearer {auth_token}"})

email_change_response = user_api_session.patch(
f"/@users/{userid}",
json={"email": "new_email@example.com"},
)

self.assertTrue(email_change_response.ok)
new_login_with_old_email_response = self.anon_api_session.post(
"/@login",
json={
"login": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertFalse(new_login_with_old_email_response.ok)
new_login_with_new_email_response = self.anon_api_session.post(
"/@login",
json={
"login": "new_email@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(new_login_with_new_email_response.ok)

def test_manager_changes_email_when_login_with_email_and_uuid_userids(self):
"""test that when login with email is enabled and a manager changes a user's email
they can log in with the new email.
The site is configured to save userids as uuid
"""
# enable use_email_as_login
security_settings = getAdapter(self.portal, ISecuritySchema)
security_settings.use_email_as_login = True
security_settings.use_uuid_as_userid = True
transaction.commit()
# Create a user
response = self.api_session.post(
"/@users",
json={
"email": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(response.ok)
userid = response.json()["id"]
transaction.commit()
anon_response = self.anon_api_session.post(
"/@login",
json={
"login": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(anon_response.ok)

email_change_response = self.api_session.patch(
f"/@users/{userid}",
json={
"email": "new_email@example.com",
},
)
self.assertTrue(email_change_response.ok)
new_login_with_old_email_response = self.anon_api_session.post(
"/@login",
json={
"login": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertFalse(new_login_with_old_email_response.ok)
new_login_with_new_email_response = self.anon_api_session.post(
"/@login",
json={
"login": "new_email@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(new_login_with_new_email_response.ok)

def test_user_changes_email_when_login_with_email_and_uuid_userids(self):
"""test that when login with email is enabled and the user changes their email
they can log in with the new email
The site is configured to save userids as uuid
"""
# enable use_email_as_login
security_settings = getAdapter(self.portal, ISecuritySchema)
security_settings.use_email_as_login = True
security_settings.use_uuid_as_userid = True

transaction.commit()
# Create a user
response = self.api_session.post(
"/@users",
json={
"email": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(response.ok)
userid = response.json()["id"]
transaction.commit()
anon_response = self.anon_api_session.post(
"/@login",
json={
"login": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(anon_response.ok)
auth_token = anon_response.json().get("token")

user_api_session = RelativeSession(self.portal_url, test=self)
user_api_session.headers.update({"Accept": "application/json"})
user_api_session.headers.update({"Authorization": f"Bearer {auth_token}"})

email_change_response = user_api_session.patch(
f"/@users/{userid}",
json={"email": "new_email@example.com"},
)

self.assertTrue(email_change_response.ok)
new_login_with_old_email_response = self.anon_api_session.post(
"/@login",
json={
"login": "howard.zinn@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertFalse(new_login_with_old_email_response.ok)
new_login_with_new_email_response = self.anon_api_session.post(
"/@login",
json={
"login": "new_email@example.com",
"password": TEST_USER_PASSWORD,
},
)
self.assertTrue(new_login_with_new_email_response.ok)

0 comments on commit 4f3bb4f

Please sign in to comment.