Skip to content

Commit

Permalink
[fc] Repository: plone.restapi
Browse files Browse the repository at this point in the history
Branch: refs/heads/main
Date: 2024-11-20T15:30:02-08:00
Author: Andrea Cecchi (cekk) <andrea.cecchi85@gmail.com>
Commit: plone/plone.restapi@694ec89

Do not change request during serialization of relation fields (#1845)

* Do not change request during serialization

* Add changelog

Files changed:
A news/1845.bugfix
M src/plone/restapi/serializer/relationfield.py
M src/plone/restapi/tests/test_dxfield_serializer.py
  • Loading branch information
davisagli committed Nov 20, 2024
1 parent 4fc1d8a commit 249b2dc
Showing 1 changed file with 10 additions and 12 deletions.
22 changes: 10 additions & 12 deletions last_commit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@ Repository: plone.restapi


Branch: refs/heads/main
Date: 2024-11-20T15:21:35-08:00
Author: Mikel Larreategi (erral) <mlarreategi@codesyntax.com>
Commit: https://github.com/plone/plone.restapi/commit/4c0991caa6a47cb84ecf7aa22763751dc753fb56
Date: 2024-11-20T15:30:02-08:00
Author: Andrea Cecchi (cekk) <andrea.cecchi85@gmail.com>
Commit: https://github.com/plone/plone.restapi/commit/694ec892dd992c5187ada334f55175d5ba7d9f08

additional tests (#1840)
Do not change request during serialization of relation fields (#1845)

* additional tests
* Do not change request during serialization

* changelog

* return a 400 Bad request when trying to change the username to an existing one
* Add changelog

Files changed:
A news/1840.internal
M src/plone/restapi/services/users/update.py
M src/plone/restapi/tests/test_services_users.py
A news/1845.bugfix
M src/plone/restapi/serializer/relationfield.py
M src/plone/restapi/tests/test_dxfield_serializer.py

b'diff --git a/news/1840.internal b/news/1840.internal\nnew file mode 100644\nindex 000000000..468f80444\n--- /dev/null\n+++ b/news/1840.internal\n@@ -0,0 +1,2 @@\n+Additional tests to login name changes\n+[erral]\ndiff --git a/src/plone/restapi/services/users/update.py b/src/plone/restapi/services/users/update.py\nindex 3d7d3b724..e2fdb1960 100644\n--- a/src/plone/restapi/services/users/update.py\n+++ b/src/plone/restapi/services/users/update.py\n@@ -107,7 +107,20 @@ def reply(self):\n if security.use_email_as_login and "email" in user_settings_to_update:\n value = user_settings_to_update["email"]\n pas = getToolByName(self.context, "acl_users")\n- pas.updateLoginName(user.getId(), value)\n+\n+ try:\n+ pas.updateLoginName(user.getId(), value)\n+ except ValueError:\n+ return self._error(\n+ 400,\n+ "Bad request",\n+ _(\n+ "Cannot update login name of user to \'${new_email}\'.",\n+ mapping={\n+ "new_email": value,\n+ },\n+ ),\n+ )\n \n roles = user_settings_to_update.get("roles", {})\n if roles:\n@@ -149,7 +162,17 @@ def reply(self):\n \n if security.use_email_as_login and "email" in user_settings_to_update:\n value = user_settings_to_update["email"]\n- set_own_login_name(user, value)\n+ try:\n+ set_own_login_name(user, value)\n+ except ValueError:\n+ return self._error(\n+ 400,\n+ "Bad request",\n+ _(\n+ "Cannot update login name of user to \'${new_email}\'.",\n+ mapping={"new_email": value},\n+ ),\n+ )\n \n else:\n if self._is_anonymous:\ndiff --git a/src/plone/restapi/tests/test_services_users.py b/src/plone/restapi/tests/test_services_users.py\nindex 3d8032076..2352f62af 100644\n--- a/src/plone/restapi/tests/test_services_users.py\n+++ b/src/plone/restapi/tests/test_services_users.py\n@@ -1663,3 +1663,139 @@ def test_user_changes_email_when_login_with_email_and_uuid_userids(self):\n },\n )\n self.assertTrue(new_login_with_new_email_response.ok)\n+\n+ def test_manager_changes_email_to_existing_when_login_with_email(self):\n+ """test that when login with email is enabled and a manager tries to change a user\'s email\n+ to a previously existing one\n+ """\n+ # enable use_email_as_login\n+ security_settings = getAdapter(self.portal, ISecuritySchema)\n+ security_settings.use_email_as_login = True\n+ transaction.commit()\n+\n+ # Create user 1\n+ response = self.api_session.post(\n+ "/@users",\n+ json={\n+ "email": "howard.zinn@example.com",\n+ "password": TEST_USER_PASSWORD,\n+ },\n+ )\n+ self.assertTrue(response.ok)\n+ userid = response.json()["id"]\n+\n+ # Create user 2\n+ response = self.api_session.post(\n+ "/@users",\n+ json={\n+ "email": "second@example.com",\n+ "password": TEST_USER_PASSWORD,\n+ },\n+ )\n+ self.assertTrue(response.ok)\n+\n+ transaction.commit()\n+\n+ # Log in\n+ anon_response = self.anon_api_session.post(\n+ "/@login",\n+ json={\n+ "login": "howard.zinn@example.com",\n+ "password": TEST_USER_PASSWORD,\n+ },\n+ )\n+ self.assertTrue(anon_response.ok)\n+\n+ # try to change the email to an existing one, it should fail\n+ email_change_response = self.api_session.patch(\n+ f"/@users/{userid}",\n+ json={\n+ "email": "second@example.com",\n+ },\n+ )\n+ self.assertFalse(email_change_response.ok)\n+ self.assertEqual(email_change_response.status_code, 400)\n+ email_change_response_json = email_change_response.json()\n+ self.assertEqual(\n+ email_change_response_json.get("error", {}).get("message"),\n+ "Cannot update login name of user to \'second@example.com\'.",\n+ )\n+\n+ # Email was not changed, so log in with the old one\n+ new_login_with_old_email_response = self.anon_api_session.post(\n+ "/@login",\n+ json={\n+ "login": "howard.zinn@example.com",\n+ "password": TEST_USER_PASSWORD,\n+ },\n+ )\n+ self.assertTrue(new_login_with_old_email_response.ok)\n+\n+ def test_user_changes_email_to_existing_one_when_login_with_email(self):\n+ """test that when login with email is enabled and the user changes their email\n+ they can log in with the new email\n+ """\n+ # enable use_email_as_login\n+ security_settings = getAdapter(self.portal, ISecuritySchema)\n+ security_settings.use_email_as_login = True\n+ transaction.commit()\n+\n+ # Create user 1\n+ response = self.api_session.post(\n+ "/@users",\n+ json={\n+ "email": "howard.zinn@example.com",\n+ "password": TEST_USER_PASSWORD,\n+ },\n+ )\n+ self.assertTrue(response.ok)\n+ userid = response.json()["id"]\n+\n+ # Create user 2\n+ response = self.api_session.post(\n+ "/@users",\n+ json={\n+ "email": "second@example.com",\n+ "password": TEST_USER_PASSWORD,\n+ },\n+ )\n+ self.assertTrue(response.ok)\n+ transaction.commit()\n+\n+ # log in with email\n+ anon_response = self.anon_api_session.post(\n+ "/@login",\n+ json={\n+ "login": "howard.zinn@example.com",\n+ "password": TEST_USER_PASSWORD,\n+ },\n+ )\n+ self.assertTrue(anon_response.ok)\n+ auth_token = anon_response.json().get("token")\n+\n+ user_api_session = RelativeSession(self.portal_url, test=self)\n+ user_api_session.headers.update({"Accept": "application/json"})\n+ user_api_session.headers.update({"Authorization": f"Bearer {auth_token}"})\n+\n+ # try to change e-mail to an existing one, it should fail\n+ email_change_response = user_api_session.patch(\n+ f"/@users/{userid}",\n+ json={"email": "second@example.com"},\n+ )\n+\n+ self.assertEqual(email_change_response.status_code, 400)\n+ email_change_response_json = email_change_response.json()\n+ self.assertEqual(\n+ email_change_response_json.get("error", {}).get("message"),\n+ "Cannot update login name of user to \'second@example.com\'.",\n+ )\n+\n+ # email was not changed, so log in with the old one\n+ new_login_with_old_email_response = self.anon_api_session.post(\n+ "/@login",\n+ json={\n+ "login": "howard.zinn@example.com",\n+ "password": TEST_USER_PASSWORD,\n+ },\n+ )\n+ self.assertTrue(new_login_with_old_email_response.ok)\n'
b'diff --git a/news/1845.bugfix b/news/1845.bugfix\nnew file mode 100644\nindex 000000000..d1d853ab6\n--- /dev/null\n+++ b/news/1845.bugfix\n@@ -0,0 +1,2 @@\n+Do not change request during relation fields serialization\n+[cekk]\ndiff --git a/src/plone/restapi/serializer/relationfield.py b/src/plone/restapi/serializer/relationfield.py\nindex d54cadb9d..3115568d0 100644\n--- a/src/plone/restapi/serializer/relationfield.py\n+++ b/src/plone/restapi/serializer/relationfield.py\n@@ -18,7 +18,7 @@\n @implementer(IJsonCompatible)\n def relationvalue_converter(value):\n if value.to_object:\n- request = getRequest()\n+ request = getRequest().clone()\n request.form["metadata_fields"] = ["UID"]\n summary = getMultiAdapter((value.to_object, request), ISerializeToJsonSummary)()\n return json_compatible(summary)\ndiff --git a/src/plone/restapi/tests/test_dxfield_serializer.py b/src/plone/restapi/tests/test_dxfield_serializer.py\nindex bac16ffcc..625ea83d5 100644\n--- a/src/plone/restapi/tests/test_dxfield_serializer.py\n+++ b/src/plone/restapi/tests/test_dxfield_serializer.py\n@@ -325,6 +325,19 @@ def test_relationlist_field_serialization_returns_list(self):\n value,\n )\n \n+ def test_relation_field_serialization_do_not_change_request(self):\n+ self.request.form["metadata_fields"] = ["foo", "bar"]\n+ doc2 = self.portal[\n+ self.portal.invokeFactory(\n+ "DXTestDocument",\n+ id="doc2",\n+ title="Referenceable Document",\n+ description="Description 2",\n+ )\n+ ]\n+ self.serialize("test_relationchoice_field", doc2)\n+ self.assertEqual(self.request.form["metadata_fields"], ["foo", "bar"])\n+\n def test_remoteurl_field_in_links_get_converted(self):\n link = self.portal[\n self.portal.invokeFactory(\n'

0 comments on commit 249b2dc

Please sign in to comment.