{ "info": { "author": "Maurits van Rees", "author_email": "m.van.rees@zestsoftware.nl", "bugtrack_url": null, "classifiers": [ "Framework :: Plone", "Framework :: Plone :: 4.1", "Framework :: Plone :: 4.2", "Framework :: Plone :: 4.3", "Programming Language :: Python" ], "description": "Introduction\n============\n\nSince Plone 4.0 you can configure Plone to allow users to login with\ntheir email address, using a setting in the Security control panel.\nThis works fine out of the box. Some improvements would be useful\nthough that need some more careful consideration before being added to\ncore Plone. That is where this package comes in.\n\nThis is a temporary package with some fixes for when you want to use\nthe email address of a user as login name in Plone 4. It also\nintroduces a few hooks for determining the user id and login name of a\nnew user.\n\n\nPlone version\n-------------\n\nThis package is tested with Plone 4.1, 4.2 and 4.3. It will not work\nin 4.0.\n\nFor Plone 3, you must use the ``collective.emaillogin`` package.\n\n\nDependencies\n------------\n\nWe need a newer version of ``Products.PluggableAuthService`` than is\navailable currently in the latest Plone versions. Assuming you are\nusing buildout for your Plone site, you need to add a line to a\nversions section::\n\n Products.PluggableAuthService = 1.10.0\n\nAny version newer than this is fine as well. If your Plone version\nalready has this version or a newer one pinned, then you do not need\nto add this line.\n\n\nWhat does this package do?\n--------------------------\n\nClearer separation between user id and login name\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe validation of the ``register`` browser view uses two methods to\nget a user id and login name::\n\n # Generate a nice user id and store that in the data.\n user_id = self.generate_user_id(data)\n # Generate a nice login name and store that in the data.\n login_name = self.generate_login_name(data)\n\nAfter this, the ``data`` dictionary will have keys ``user_id`` and\n``login_name`` set accordingly.\n\nWe avoid as much as possible the use of ``username`` as a variable,\nbecause no one ever knows if that is meant as a user id or as a login\nname. In standard Plone this is always the same, but this need not be\ntrue, especially when using the email address as login name.\n\nThese changes are intended to be merged to ``plone.app.users``.\n\n\nControl over user ids\n~~~~~~~~~~~~~~~~~~~~~\n\nAn ``IUserIdGenerator`` interface is defined. This is used in the new\n``generate_user_id`` method of the ``register`` browser view (also\nused when adding a new user as admin). Two sample implementations::\n\n def uuid_userid_generator(data=None):\n # Return a uuid, independent of the data.\n # This is available in utils.py in the plone.app.users patches.\n from zope.component import getUtility\n from plone.uuid.interfaces import IUUIDGenerator\n generator = getUtility(IUUIDGenerator)\n return generator()\n\n def login_name_as_userid_generator(data):\n # We like to keep it simple.\n return data.get('username')\n\nIn ``generate_user_id`` we try a few options for coming up with a good\nuser id:\n\n1. We query a utility, so integrators can register a hook to\n generate a user id using their own logic::\n\n generator = queryUtility(IUserIdGenerator)\n if generator:\n userid = generator(data)\n if userid:\n data['user_id'] = userid\n return userid\n\n2. If ``use_uuid_as_userid`` is set in the site_properties, we\n generate a uuid. This is a new property introduced by this\n package and can be set in the Security control panel.\n\n3. If a username is given and we do not use email as login,\n then we simply return that username as the user id.\n\n4. We create a user id based on the full name, if that is\n passed. This may result in an id like ``bob-jones-2``.\n\nWhen the email address is used as login name, we originally\nused the email address as user id as well. This has a few\npossible downsides, which are the main reasons for the new,\npluggable approach:\n\n- It does not work for some valid email addresses.\n\n- Exposing the email address in this way may not be wanted.\n\n- When the user later changes his email address, the user id\n will still be his old address. It works, but may be\n confusing.\n\nAnother possibility would be to simply generate a uuid, but that is\nugly. We could certainly try that though: the big plus here would be\nthat you then cannot create a new user with the same user id as a\npreviously existing user if this ever gets removed. If you would get\nthe same id, this new user would get the same global and local roles,\nif those have not been cleaned up.\n\nWhen a user id is chosen, the ``user_id`` key of the data gets\nset and the user id is returned.\n\nThese changes are intended to be merged to ``plone.app.users``.\n\n\nControl over login names\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nSimilarly, an ``ILoginNameGenerator`` interface is defined.\n\nUsually the login name and user id are the same, but this is\nnot necessarily true. When using the email address as login\nname, we may have a different user id, generated by calling\nthe generate_user_id method.\n\nWe try a few options for coming up with a good login name:\n\n1. We query a utility, so integrators can register a hook to\n generate a login name using their own logic::\n\n pas = getToolByName(self.context, 'acl_users')\n generator = queryUtility(ILoginNameGenerator)\n if generator:\n login_name = generator(data)\n if login_name:\n login_name = pas.applyTransform(login_name)\n data['login_name'] = login_name\n return login_name\n\n2. If a username is given and we do not use email as login,\n then we simply return that username as the login name.\n\n3. When using email as login, we use the email address.\n\nIn all cases, we call PAS.applyTransform on the login name, if\nthat is defined. This is a recent addition to PAS, currently\nunder development.\n\nWhen a login name is chosen, the ``login_name`` key of the data gets\nset and the login name is returned.\n\nThese changes are intended to be merged to ``plone.app.users``.\n\n\nLowercase login names\n~~~~~~~~~~~~~~~~~~~~~\n\nWe store login names as lowercase. The email addresses themselves can\nactually be mixed case, though that is not really by design, more a\n(happy) circumstance.\n\nThis needs branch ``maurits-login-transform`` of\n``Products.PluggableAuthService``. That branch introduces a property\n``login_transform``. Setting this to ``lower`` the ``lower`` method\nof PAS is called whenever a login name is given.\n\nAll relevant places in ``plone.app.users`` have been changed to take\nthis new property into account, using code like this::\n\n login_name = pas.loginTransform(login_name)\n\nIn the security panel of ``plone.app.controlpanel`` we change the\n``set_use_email_as_login`` method to set ``login_transform`` to lower\ncase when switching on email as login name. For safety, we never\nchange this back to the default empty string. This is fine for normal\nnon-email login names as well.\n\nNote that when ``login_transform`` is ``lower``, the end user can\nlogin with upper case ``JOE`` and he will then be logged in with login\nname ``joe``, as long as the password is correct of course. If you\nsomehow still have an upper or mixed case login name, you cannot\nlogin.\n\nSetting the login_transform to a non empty string will\nautomatically apply this transform to all existing logins in your\ndatabase.\n\nNote: when this is merged to core Plone, login names will not be\ntransformed to lowercase by default. The option will simply be\navailable if the site admin wants it. Switching on email as login\nwill also switch on lowercase login names.\n\n\nUpdating login names\n--------------------\n\nWe have a patch for the ``ZODBMutablePropertyProvider`` of\n``Products.PlonePAS`` that adds two new but empty methods required by\nthe changed ``IUserEnumerationPlugin`` interface of PAS::\n\n def updateUser(self, user_id, login_name):\n pass\n\n\n def updateEveryLoginName(self, quit_on_first_error=True):\n pass\n\nThis has been merged to ``Products.PlonePAS``.\n\n\nControl panels\n~~~~~~~~~~~~~~\n\nSwitching email as login name on or off in the security panel now\nautomatically updates existing login names. It may fail when there\nare duplicates.\n\nThe updating of existing users used to be done in the\n``@@migrate-to-emaillogin`` view (class ``EmailView``) from\n``plone.app.controlpanel``. We have simplified this page to only\nsearch for duplicate login names. You can search for duplicate email\naddresses or duplicate user ids, always lower case.\n\nThe security panel now has an option ``Use UUID user ids``, by default\nswitched off.\n\n\nSet own login name\n~~~~~~~~~~~~~~~~~~\n\nThe ``Products.CMFPlone.utils.set_own_login_name`` method is\nsimplified, with much of the former code being moved to PAS\nitself::\n\n def set_own_login_name(member, loginname):\n \"\"\"Allow the user to set his/her own login name.\n\n If you have the Manage Users permission, you can update the login\n name of another member too, though the name of this function is a\n bit weird then. Historical accident.\n \"\"\"\n pas = getToolByName(member, 'acl_users')\n mt = getToolByName(member, 'portal_membership')\n if member.getId() == mt.getAuthenticatedMember().getId():\n pas.updateOwnLoginName(loginname)\n return\n secman = getSecurityManager()\n if not secman.checkPermission(ManageUsers, member):\n raise Unauthorized('You can only change your OWN login name.')\n pas.updateLoginName(member.getId(), loginname)\n\n\nInstallation\n~~~~~~~~~~~~\n\nWhen installing this add-on in the Add-ons control panel, the\nfollowing is done.\n\n- It adds the ``use_uuid_as_userid`` site property, by default False.\n\n- If email as login is already used in the site, we set\n ``login_transform`` to ``lower``. This could give an error and quit\n the installation. Maybe we want to catch this and just log a\n warning.\n\n- It explicitly enables email as login name. This would *not* be done\n when merging this package back to core Plone.\n\nChangelog\n=========\n\n1.3 (2013-02-19)\n----------------\n\n- Depend on ``Products.PluggableAuthService >= 1.10.0`` which has\n been released recently.\n [maurits]\n\n\n1.2 (2013-01-23)\n----------------\n\n- Make sure user ids are strings, not unicode.\n [maurits]\n\n\n1.1 (2013-01-23)\n----------------\n\n- Make sure the Manage Users permission is checked in set_own_login_name.\n [maurits]\n\n\n1.0 (2013-01-22)\n----------------\n\n- Initial release", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pypi.python.org/pypi/collective.emaillogin4", "keywords": "", "license": "GPL", "maintainer": null, "maintainer_email": null, "name": "collective.emaillogin4", "package_url": "https://pypi.org/project/collective.emaillogin4/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/collective.emaillogin4/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pypi.python.org/pypi/collective.emaillogin4" }, "release_url": "https://pypi.org/project/collective.emaillogin4/1.3/", "requires_dist": null, "requires_python": null, "summary": "Emaillogin fixes for Plone 4", "version": "1.3" }, "last_serial": 3630435, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "48e20371a92135a451a1ca092abcf2b9", "sha256": "6de71192e4f91d8a336def1ec5945c9d13e79b324538144d92e991b148d72b98" }, "downloads": -1, "filename": "collective.emaillogin4-1.0.zip", "has_sig": false, "md5_digest": "48e20371a92135a451a1ca092abcf2b9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 59122, "upload_time": "2013-01-22T14:55:03", "url": "https://files.pythonhosted.org/packages/bb/c5/2775a7ee22c2c8612c52610880b559a848491f3bc2bbf3f6ff70151092f6/collective.emaillogin4-1.0.zip" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "d86e7a67cce294b745c30ccb0a47870f", "sha256": "fc47d71af68b9a1ed365780db6d0f8e449313fc650fb1927ffe9fd35f47a6886" }, "downloads": -1, "filename": "collective.emaillogin4-1.1.zip", "has_sig": false, "md5_digest": "d86e7a67cce294b745c30ccb0a47870f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 60370, "upload_time": "2013-01-22T23:22:35", "url": "https://files.pythonhosted.org/packages/96/33/800b912849fde3f7df23472b24e71d74b45fc028d215a382fe2c2cc19801/collective.emaillogin4-1.1.zip" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "e2c047f276d9a886b1e22cf203a5aadd", "sha256": "87d708b209c62728d6d17c707a48c8a4f4be5897dfb801e2425230a2e2c6f6dd" }, "downloads": -1, "filename": "collective.emaillogin4-1.2.zip", "has_sig": false, "md5_digest": "e2c047f276d9a886b1e22cf203a5aadd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 60460, "upload_time": "2013-01-23T18:30:06", "url": "https://files.pythonhosted.org/packages/5b/5b/329790920f8c501d3b42a047be9c7ab0a956840ade2f215fd4940885e033/collective.emaillogin4-1.2.zip" } ], "1.3": [ { "comment_text": "", "digests": { "md5": "b296e58d1e6b20b395e71ce221ac76f2", "sha256": "ea257d99d8cc88229ccde98f35e97faafb35560ef7d343f38c76588fd4c4a77b" }, "downloads": -1, "filename": "collective.emaillogin4-1.3.zip", "has_sig": false, "md5_digest": "b296e58d1e6b20b395e71ce221ac76f2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 60151, "upload_time": "2013-02-19T17:28:27", "url": "https://files.pythonhosted.org/packages/9a/80/ba37ee2963128c18454a7f644d96173e6098c57bbb57e3c5a166e7192533/collective.emaillogin4-1.3.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b296e58d1e6b20b395e71ce221ac76f2", "sha256": "ea257d99d8cc88229ccde98f35e97faafb35560ef7d343f38c76588fd4c4a77b" }, "downloads": -1, "filename": "collective.emaillogin4-1.3.zip", "has_sig": false, "md5_digest": "b296e58d1e6b20b395e71ce221ac76f2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 60151, "upload_time": "2013-02-19T17:28:27", "url": "https://files.pythonhosted.org/packages/9a/80/ba37ee2963128c18454a7f644d96173e6098c57bbb57e3c5a166e7192533/collective.emaillogin4-1.3.zip" } ] }