diff --git a/news/4292.bugfix b/news/4292.bugfix new file mode 100644 index 00000000..d3e01008 --- /dev/null +++ b/news/4292.bugfix @@ -0,0 +1,3 @@ +Fix ``plone.api.user.create()`` to respect ``use_uuid_as_userid`` and +``use_email_as_login`` registry settings, as well as custom ``IUserIdGenerator`` +and ``ILoginNameGenerator`` utilities. diff --git a/setup.py b/setup.py index 2d2d1dd4..7355b7b0 100644 --- a/setup.py +++ b/setup.py @@ -27,6 +27,7 @@ "Products.PlonePAS", "Products.CMFPlone", "decorator", + "plone.app.users", "plone.app.uuid", "plone.app.dexterity", "plone.app.intid", diff --git a/src/plone/api/tests/test_user.py b/src/plone/api/tests/test_user.py index a7140bdb..4f8283fb 100644 --- a/src/plone/api/tests/test_user.py +++ b/src/plone/api/tests/test_user.py @@ -113,6 +113,9 @@ def test_create_with_username(self): ) self.assertEqual(user.getUserName(), "chuck@norris.org") + # Delete user before recreating with different login settings, + # because generate_user_id uses username as user_id in both cases. + api.user.delete(user=user) self._set_emaillogin(False) user = api.user.create( diff --git a/src/plone/api/user.py b/src/plone/api/user.py index 96a47083..2e93b98f 100644 --- a/src/plone/api/user.py +++ b/src/plone/api/user.py @@ -65,16 +65,29 @@ def create( "that is not email so you need to pass a username.", ) + # Generate user_id and login_name using the canonical implementation + # from plone.app.users, respecting use_uuid_as_userid, + # use_email_as_login, IUserIdGenerator, and ILoginNameGenerator. + from plone.app.users.utils import generate_login_name + from plone.app.users.utils import generate_user_id + + site = portal.get() + data = { + "username": username, + "email": email, + "fullname": properties.get("fullname", ""), + } + user_id = generate_user_id(site, data) or username or email + login_name = generate_login_name(site, data) or username or email + registration = portal.get_tool("portal_registration") - user_id = use_email_as_username and email or username # Generate a random 8-char password if not password: chars = string.ascii_letters + string.digits password = "".join(random.choice(chars) for char in range(8)) - properties.update(username=user_id) - properties.update(email=email) + properties.update(username=user_id, email=email) registration.addMember( user_id, @@ -82,7 +95,14 @@ def create( roles, properties=properties, ) - return get(username=user_id) + + # If user_id differs from login_name (e.g. UUID as user id with + # email as login), update the login name accordingly. + if user_id != login_name: + pas = portal.get_tool("acl_users") + pas.updateLoginName(user_id, login_name) + + return get(userid=user_id) @mutually_exclusive_parameters("userid", "username")