{ "info": { "author": "Souheil Chelfouh", "author_email": "souheil@chelfouh.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Zope3", "Intended Audience :: Other Audience", "License :: OSI Approved :: GNU General Public License (GPL)", "Operating System :: OS Independent", "Programming Language :: Python" ], "description": "``dolmen.app.authentication`` is the package responsible for the users and\ngroups management in a Dolmen application. Built on the on the top of\n``dolmen.authentication`` and ``zope.pluggableauth``, it provides a\nset of plugins and base classes that can help building a complex users\n& groups system.\n\nInitial Grok imports\n====================\n\n >>> import grok\n >>> from grokcore.component.testing import grok_component\n\n\nCredentials plugins\n===================\n\n >>> from zope.pluggableauth.interfaces import ICredentialsPlugin\n\nCredentials plugins are responsible for the extraction of credentials,\nin order to identify a user. ``dolmen.app.authentication`` provides a\nsingle plugin, out of the box - Cookies Credentials.\n\nCookies Credentials\n-------------------\n\nThe cookie credentials plugin extracts the credentials from cookies.\nThis plugin is based on Philipp von Weitershausen's work\n(``wc.cookiecredentials``). It has been reimplemented to avoid the use\nof the ``zope.app`` packages and allow more flexibility in the long run.\n\nThis plugin provides the following capabilities:\n\n- challenge the user to enter username and password through a login\n form;\n\n- save those credentials to a cookie from which it can read them back\n at any later time.\n\nTo check if the credentials can correctly be exacted, we can forge the\ncookie ourselves in a test request::\n\n >>> import base64\n >>> from zope.publisher.browser import TestRequest\n\n >>> cookie = base64.encodestring('mgr:mgrpw')\n >>> request = TestRequest()\n >>> request._cookies = {'dolmen.authcookie': cookie}\n\nCalling the plugin credentials extractor will give us exactly what we\nneed to proceed to the authentication::\n\n >>> from zope.interface.verify import verifyObject\n >>> from dolmen.app.authentication.plugins import CookiesCredentials\n\n >>> plugin = CookiesCredentials()\n >>> verifyObject(ICredentialsPlugin, plugin)\n True\n\n >>> print plugin.extractCredentials(request)\n {'login': u'mgr', 'password': u'mgrpw'}\n\n\nAuthenticator Plugins\n=====================\n\n >>> from zope.pluggableauth.interfaces import IAuthenticatorPlugin\n\nAuthenticator plugins uses extracted credentials in order to retrieve\nand identify principals. ``dolmen.app.authentication`` provides two\nplugins - Global Registry Authentication & Principal Folder Authentication\n\n\nGlobal Registry Authentication\n------------------------------\n\nIn order to register principals, the ``zope.principalregistry``\npackage provides a global registry that is not persistent and\nre-constructed at each startup. The Global Registry Authenticator is\nmeant to look up the principal inside that global registry.\n\nWe verify the integrity of our implementation against the\nrequirements::\n\n >>> from dolmen.app.authentication import plugins\n >>> IAuthenticatorPlugin.implementedBy(plugins.GlobalRegistryAuth)\n True\n\n >>> plugin = plugins.GlobalRegistryAuth()\n >>> verifyObject(IAuthenticatorPlugin, plugin)\n True\n\nIn order to test this plugin, we registered a user, called \"mgr\" in\nthe global registry. We'll test the look up using \"mgr\" credentials::\n\n >>> user = plugin.authenticateCredentials(\n ... {'login': u\"mgr\", \"password\": u\"mgrpw\"})\n >>> print user\n \n\nWrong credentials will make the authentication return None::\n\n >>> user = plugin.authenticateCredentials(\n ... {'login': u\"mgr\", \"password\": u\"wrongpass\"})\n >>> user is None\n True\n\n >>> user = plugin.authenticateCredentials(\n ... {'login': u\"anon\", \"password\": u\"wrongpass\"})\n >>> user is None\n True\n\nIt is not possible to get the principal info alone::\n\n >>> print plugin.principalInfo('zope.mgr')\n None\n\n >>> print plugin.principalInfo('zorglub')\n None\n\n\nPrincipal Folder Authentication\n-------------------------------\n\n``dolmen.app.authentication`` introduces another authenticator plugin\nmeant to store and retrieve persistent principals. This plugin is a\ncontainer that can store IPrincipal objects and retrieve them\nfollowing the IAuthenticatorPlugin's prescriptions.\n\nWe verify the integrity of our implementation against the\nrequirements::\n\n >>> from dolmen.app.authentication import plugins\n >>> IAuthenticatorPlugin.implementedBy(plugins.PrincipalFolderPlugin)\n True\n\n >>> plugin = plugins.PrincipalFolderPlugin()\n >>> verifyObject(IAuthenticatorPlugin, plugin)\n True\n\nIn order to test this plugin, we have to create an IPrincipal object\nand store it inside the plugin. Then, we can test the look up.\n\nIn order to make the authentication pluggable, the principal\nauthenticator plugin relies on 3 interfaces: \n\n- IAccountStatus : if an adaptation exist to this interface from the\n IPrincipal object, it is used to figure out if the principal can\n login or not. It allows disabling a user account and computing that \n disability.\n\n- IPasswordChecker: this adapter is used to check the credentials. If\n it doesnt exist (or if the IPrincipal object doesn't provide this\n interface), the authentication is aborted and None is returned.\n\n- IPrincipalInfo: unlike the previous plugin, the Principal Folder\n authenticator doesn't directly return a PrincipalInfo object, but\n uses an adapter to retrieve the appropriate principal info\n object. This is required in order to plug specific behavior into our\n authentication system.\n\n\nLet's first implement a basic IPrincipalObject. Once stored, we'll be\nable to start the look ups and the adapters implementations::\n\n >>> from dolmen.app.authentication.tests import User\n\nSee the implementation below::\n\n from dolmen.authentication import IPrincipal\n from zope.interface import implements\n\n class User(object):\n implements(IPrincipal)\n\n def __init__(self, id, title=u\"\", desc=u\"\"):\n self.id = id\n self.title = title or id\n self.description = desc\n self.groups = []\n\nWe can verify our implementation against the interface::\n\n >>> from dolmen.authentication import IPrincipal\n >>> stilgar = User(u\"stilgar\")\n >>> verifyObject(IPrincipal, stilgar)\n True\n\nWe can set up a simple view for our User class::\n\n >>> from grokcore.layout import Page\n\n >>> class UserView(Page):\n ... grok.name('index')\n ... grok.context(User)\n ...\n ... def render(self):\n ... return \"\" % self.context.id\n\n >>> grok_component('index', UserView)\n True\n\nThe implementation is consistent. We can now persist the principal in\nthe plugin container::\n\n >>> plugin['stilgar'] = stilgar\n >>> print [user for user in plugin.keys()]\n [u'stilgar']\n\nWe can now try to look up the principal, using the authentication API::\n\n >>> found = plugin.authenticateCredentials(\n ... {'login': 'stilgar', 'password': 'boo'})\n >>> found is None\n True\n\nThe principal is not found : we do not have an adapter to\nIPasswordChecker available, therefore the authentication process has\nbeen aborted.\n\nProviding the adapter will allow us to successfully retrieve the\nprincipal::\n\n >>> from dolmen.authentication import IPasswordChecker\n\n >>> class GrantingAccessOnBoo(grok.Adapter):\n ... grok.context(IPrincipal)\n ... grok.provides(IPasswordChecker)\n ...\n ... def checkPassword(self, pwd):\n ... if pwd == 'boo':\n ... return True\n\n >>> grok_component('booing', GrantingAccessOnBoo)\n True\n \n >>> found = plugin.authenticateCredentials(\n ... {'login': 'stilgar', 'password': 'boo'})\n >>> found is not None\n True\n\n\nOf course, providing a wrong password will return None::\n\n >>> found = plugin.authenticateCredentials(\n ... {'login': 'stilgar', 'password': 'not boo'})\n >>> found is None\n True\n\nWe can also lookup the principal with its id::\n\n >>> print plugin.principalInfo('stilgar')\n \n\n >>> print plugin.principalInfo(\"unknown\")\n None\n\nAs seen previously, it is possible to switch on and off the ability to\nlog in, for a given user, thanks to the IAccountStatus interface::\n\n >>> from dolmen.authentication import IAccountStatus\n\n >>> class AllowLogin(grok.Adapter):\n ... grok.context(IPrincipal)\n ... grok.provides(IAccountStatus)\n ... \n ... @property\n ... def status(self):\n ... return \"No status information available\"\n ...\n ... def check(self):\n ... if self.context.id != \"stilgar\":\n ... return True\n ... return False\n\n >>> grok_component('allow', AllowLogin)\n True\n\nIn this example, we explictly disallow the user with the identifier\n\"stilgar\" to be retrieved by the login::\n\n >>> found = plugin.authenticateCredentials(\n ... {'login': 'stilgar', 'password': 'boo'})\n >>> found is None\n True\n\n\nSetting up a site\n=================\n\nIn order to test the advanced features of the package, we'll set up a\nfamiliar environment. Doing so, we can test the behavior of our\npackage in the context of a real Dolmen site::\n\n >>> from dolmen.app.site import Dolmen\n >>> root = getRootFolder()\n\n >>> site = Dolmen()\n >>> grok.notify(grok.ObjectCreatedEvent(site))\n >>> root['site'] = site\n\n >>> from zope.authentication.interfaces import IAuthentication\n >>> from zope.pluggableauth import PluggableAuthentication\n >>> from dolmen.app.authentication import initialize_pau\n\n >>> PAU = PluggableAuthentication()\n >>> len(PAU.authenticatorPlugins)\n 0\n >>> len(PAU.credentialsPlugins)\n 0\n\n >>> initialize_pau(PAU)\n >>> print PAU.authenticatorPlugins\n ('globalregistry',)\n >>> print PAU.credentialsPlugins\n ('cookies', 'No Challenge if Authenticated')\n\n >>> site['auth'] = PAU\n >>> lsm = site.getSiteManager()\n >>> lsm.registerUtility(PAU, IAuthentication)\n\n >>> from grokcore.layout import Layout\n >>> from zope.interface import Interface\n\n >>> class Layout(Layout):\n ... grok.name('')\n ... grok.context(Interface)\n ...\n ... def render(self):\n ... return u''\n ...\n ... def __call__(self, view):\n ... return u\"\\n\" + unicode(view.render())\n\n >>> grok_component('layout', Layout)\n True\n\n >>> from dolmen.forms import crud\n >>> class Edit(crud.Edit):\n ... grok.context(Dolmen)\n ... grok.require('test.Edit')\n\n >>> grok_component('editsite', Edit)\n True\n\n >>> class DolmenIndex(Page):\n ... grok.name('index')\n ... grok.context(Dolmen)\n ...\n ... def render(self):\n ... return \"Homepage\"\n\n >>> grok_component('indexsite', DolmenIndex)\n True\n\n\nLogging in\n==========\n\nUnAuthorized\n------------\n\nImagine you go to a page that anonymous users don't have access to::\n\n >>> from zope.app.wsgi.testlayer import Browser\n >>> browser = Browser()\n >>> browser.handleErrors = False\n\n >>> browser.open(\"http://localhost/site/@@edit\")\n Traceback (most recent call last):\n ...\t \t \n Unauthorized: ...\n\n\nThe login page\n--------------\n\nTo get the right credentials, we can simply log in, using the login\nform provided by ``dolmen.app.authentication``::\n\n >>> browser.open('http://localhost/site/@@login')\n >>> loginpage = browser.contents\n >>> 'id=\"login\"' in loginpage\n True\n >>> 'id=\"password\"' in loginpage\n True\n\n >>> browser.getControl('Username').value = 'mgr'\n >>> browser.getControl('Password').value = 'mgrpw'\n >>> browser.getControl('Log in').click()\n\n >>> browser.url\n 'http://localhost/site'\n\n\nManaging the authentication plugins\n====================================\n\n``dolmen.app.authentication`` provides a way to enable and disable the\ndifferent authentication plugins.\n\nIn order to keep the elements tidied up, in the site,\n``dolmen.app.authentication`` assumes that the authenticator plugins\nare persisted inside the PAU container.\n\nLet's have a concrete exemple with a PrincipalFolder plugin::\n\n >>> members = plugins.PrincipalFolderPlugin()\n >>> grok.notify(grok.ObjectCreatedEvent(members))\n >>> PAU['members'] = members\n\nAt this point, the PrincipalFolder is created and persisted. As we\nnotice, the folder is created inside the PAU utility container.\n\nAt this point, we can access the management view::\n\n >>> browser.open(\"http://localhost/site/auth/@@authenticators\")\n >>> print browser.contents\n \n
\n

Edit the authentication sources

\n ...\n\nThe \"members\" principal folder is not yet activated.\n\nLet's create a User object inside it::\n\n >>> chani = User(u\"chani\", title=u\"Sihaya\")\n >>> PAU['members']['chani'] = chani\n\nNow, with a new browser, let's try to login::\n\n >>> new_browser = Browser()\n >>> new_browser.open('http://localhost/site/@@login')\n >>> new_browser.getControl('Username').value = 'chani'\n >>> new_browser.getControl('Password').value = 'boo'\n >>> new_browser.getControl('Log in').click()\n\n >>> \"Login failed\" in new_browser.contents\n True\n\nUsing the management view mechanisms, we can activate our principal\nfolder::\n\n >>> from dolmen.app.authentication.browser import management\n >>> adapter = management.IActiveFolders(PAU)\n >>> adapter.activeFolders\n ()\n >>> adapter.activeFolders = (u'members',)\n\nThe principal folder is now activated. Let's retry to log in::\n\n >>> new_browser = Browser()\n >>> new_browser.handleErrors = False\n\n >>> new_browser.open('http://localhost/site/@@login')\n >>> new_browser.getControl('Username').value = 'chani'\n >>> new_browser.getControl('Password').value = 'boo'\n >>> new_browser.getControl('Log in').click()\n\n >>> \"Login failed\" in new_browser.contents\n False\n\n >>> print new_browser.url\n http://localhost/site\n\n\nCreating roles\n==============\n\n >>> class Editor(grok.Role):\n ... grok.name('testEditor')\n ... grok.title(u\"Editor\")\n ... grok.description(u\"A basic editor.\")\n ... grok.permissions('test.Edit')\n\n >>> grok_component('editor', Editor)\n True\n\n\nManaging the users\n==================\n\nUsers can be granted roles. This can be done through a view, with the\nuser as the context::\n\n >>> browser.handleErrors = False\n >>> browser.open(\"http://localhost/site/auth/members/chani/@@grant_roles\")\n >>> browser.getControl(name='form.field.roles').value = ['testEditor']\n\n >>> browser.handleErrors = False\n >>> browser.getControl('Update').click()\n\n\nThis view is possible thanks to an adapter, useable on any\nIPrincipals. Let's check if our previous action did its work::\n\n >>> from zope.component.hooks import setSite\n >>> setSite(site) # we got to the context of our site\n\n >>> from dolmen.app.authentication.browser import roles\n >>> role_controller = roles.IPrincipalRoles(chani)\n >>> role_controller.roles\n set([u'testEditor'])\n\nThe selected roles are there. We can modify them very easily::\n\n >>> role_controller.roles = [u'testEditor']\n >>> role_controller.roles\n set([u'testEditor'])\n\nThe role management applies the changes on the site object\nitself. Let's verify if the role has been correctly applied::\n\n >>> from zope.securitypolicy.interfaces import IPrincipalRoleManager\n >>> prm = IPrincipalRoleManager(site)\n >>> print prm.getRolesForPrincipal(chani.id)\n [(u'testEditor', PermissionSetting: Allow)]\n\n\nLogging out\n===========\n\nWe can also manually destroy the cookie by invoking the logout page::\n\n >>> 'dolmen.authcookie' in browser.cookies.keys()\n True\n\n >>> browser.open(\"http://localhost/site/@@logoutaction\")\n >>> 'dolmen.authcookie' in browser.cookies.keys()\n False\n\n >>> browser.url\n 'http://localhost/site/logout.html'\n\nChanges\n=======\n\n1.1.1 (2013-11-11)\n------------------\n\n- Fixed a cookie encoding error.\n\n\n1.1 (2013-11-06)\n----------------\n\n- Removed all dolmen.app dependencies in order to free the package\n from useless ties. This is acheived by removing the integration of\n the menu entries and base schemas.\n\n\n1.0b4 (2013-10-31)\n------------------\n\n- PrincipalFolderPlugin requires a title.\n\n- Corrected the decoding of the cookie value.\n\n\n1.0b3 (2010-11-18)\n------------------\n\n- Corrected the way vocabularies are declared in the managing\n views(role granting and user folders selection. A pluggability is\n present but the base vocabularies are not returned if no component\n is found.\n\n\n1.0b2 (2010-11-16)\n------------------\n\n- Change in IChangePassword. Password can be a plain str or a unicode value\n now (via IProtected). IChangePassword then provides the schema for the form.\n See corresponding change in dolmen.authentication.\n\n- The GlobalRegistry plugin has been fixed. It will no longer trigger\n the AuthenticatedPrincipalCreated event. This solves an important\n bug : the event's handlers used to consider all principals from the\n GlobalRegistry to be authenticated, even the unauthenticated ones.\n\n\n1.0b1 (2010-07-28)\n------------------\n\n- Internationalized the code and added French translation.\n\n- Corrected the role granting UI and exposed it through a contextual tab.\n\n- Improved the tests coverage.\n\n\n1.0a3 (2010-06-25)\n------------------\n\n- The GlobalRegistry plugin no longer raises an error when a principalInfo\n is not Found. Instead, it returns None, as specified by IAuthentication.\n Tests have been added to fix that behavior and the PrincipalFolder's one.\n\n\n1.0a2 (2010-06-25)\n------------------\n\n- The PrincipalFolder no longer raises an error when a principalInfo\n is not Found. Instead, it returns None, as specified by\n IAuthentication.\n\n\n1.0a1 (2010-06-04)\n------------------\n\n- Removed unused and illogical rights: \"CanLogin\" & \"CanLogout\".\n\n- ``dolmen.app.authentication`` now uses dolmen.menu to create menus and register entries.\n\n- We now use the ``zeam.form`` Form library instead of z3c.form\n\n\n0.1.1 (2010-05-31)\n------------------\n\n- Updated translations.\n\n\n0.1 (2010-05-30)\n----------------\n\n- Initial release.", "description_content_type": null, "docs_url": null, "download_url": "http://pypi.python.org/pypi/dolmen.app.authentication", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://tracker.trollfot.org/", "keywords": "Grok Zope3 CMS Dolmen", "license": "GPL", "maintainer": null, "maintainer_email": null, "name": "dolmen.app.authentication", "package_url": "https://pypi.org/project/dolmen.app.authentication/", "platform": "Any", "project_url": "https://pypi.org/project/dolmen.app.authentication/", "project_urls": { "Download": "http://pypi.python.org/pypi/dolmen.app.authentication", "Homepage": "http://tracker.trollfot.org/" }, "release_url": "https://pypi.org/project/dolmen.app.authentication/1.1.1/", "requires_dist": null, "requires_python": null, "summary": "Dolmen CMS authentication package", "version": "1.1.1" }, "last_serial": 916330, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "ee26963fd3c77d95944f6a50ee7f9a57", "sha256": "b5ee79973c5a0b287d3734844982b61969551f4882dd903bb1006b3df00372bd" }, "downloads": -1, "filename": "dolmen.app.authentication-0.1.tar.gz", "has_sig": false, "md5_digest": "ee26963fd3c77d95944f6a50ee7f9a57", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21345, "upload_time": "2010-05-30T16:53:32", "url": "https://files.pythonhosted.org/packages/5f/be/0d585edb7dfdd16286753e8369fe8aa4ebc642e9345f1482bd04b2e33681/dolmen.app.authentication-0.1.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "121461d613a21625ceeb83b3deba3be4", "sha256": "5fd197414d57edbaa24a0cec630ff08e41da04bb31f5d671bbb5e8cfce23ffbf" }, "downloads": -1, "filename": "dolmen.app.authentication-0.1.1.tar.gz", "has_sig": false, "md5_digest": "121461d613a21625ceeb83b3deba3be4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21504, "upload_time": "2010-05-31T02:01:13", "url": "https://files.pythonhosted.org/packages/7c/ab/282caa0d01973e4293a04de0c2476aa41acc1da034df91139ebcd5ac58b8/dolmen.app.authentication-0.1.1.tar.gz" } ], "1.0a1": [ { "comment_text": "", "digests": { "md5": "e4e0150cf354c5a0af84aeb141cad612", "sha256": "5bf631fcf5b27d33d4ec2f43d4f5eebe47d18931dfa7608ab4bced5f17a6bb27" }, "downloads": -1, "filename": "dolmen.app.authentication-1.0a1.tar.gz", "has_sig": false, "md5_digest": "e4e0150cf354c5a0af84aeb141cad612", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21897, "upload_time": "2010-06-04T16:20:53", "url": "https://files.pythonhosted.org/packages/15/44/d3897be8fa5af5f0c23ec8da6c494d866f9e9879d7cacdec142f09eb5bbf/dolmen.app.authentication-1.0a1.tar.gz" } ], "1.0a2": [ { "comment_text": "", "digests": { "md5": "11e9a7ac36c5edebec3e07cb37ffc326", "sha256": "28cfd5ebae7badf960330237b54debe28db080a121082f8b8890d57b29bbe5ad" }, "downloads": -1, "filename": "dolmen.app.authentication-1.0a2.tar.gz", "has_sig": false, "md5_digest": "11e9a7ac36c5edebec3e07cb37ffc326", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22196, "upload_time": "2010-06-25T21:10:05", "url": "https://files.pythonhosted.org/packages/d5/7a/9d002aaae35d7c08fbff474f67a30bab9fb3a330ff00641718799582f1e8/dolmen.app.authentication-1.0a2.tar.gz" } ], "1.0a3": [ { "comment_text": "", "digests": { "md5": "2fe4bb14367db68038a06b5c28577949", "sha256": "d7f0524110d6e7da5486739320f7b4156eeec5fe0ba5eb15755052c0d89bca76" }, "downloads": -1, "filename": "dolmen.app.authentication-1.0a3.tar.gz", "has_sig": false, "md5_digest": "2fe4bb14367db68038a06b5c28577949", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22245, "upload_time": "2010-06-25T21:23:47", "url": "https://files.pythonhosted.org/packages/86/af/5db3f5ff939ba7e430ac617c7803a59d8fd07d19ba9f6981ec5014e43e2c/dolmen.app.authentication-1.0a3.tar.gz" } ], "1.0b1": [ { "comment_text": "", "digests": { "md5": "ac25ef47fc1cf0b68aff3551eb8c20a0", "sha256": "eba296d1ede1e90a3373590b511d2baeae8373fe6cf49a658848a858c9218e25" }, "downloads": -1, "filename": "dolmen.app.authentication-1.0b1.tar.gz", "has_sig": false, "md5_digest": "ac25ef47fc1cf0b68aff3551eb8c20a0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23283, "upload_time": "2010-07-28T22:42:16", "url": "https://files.pythonhosted.org/packages/f8/05/f58e6bcdc89ec11363f530179a398794ab47c78a4d8e151c055db6e6c5b5/dolmen.app.authentication-1.0b1.tar.gz" } ], "1.0b2": [ { "comment_text": "", "digests": { "md5": "0955fb755e588a2e1fc80d67af3e442d", "sha256": "8eb03c2ebaf43aa7cee23f8141d02da72d77990f5d959a8bb7b1e0c57947a48a" }, "downloads": -1, "filename": "dolmen.app.authentication-1.0b2.tar.gz", "has_sig": false, "md5_digest": "0955fb755e588a2e1fc80d67af3e442d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24328, "upload_time": "2010-11-16T15:22:20", "url": "https://files.pythonhosted.org/packages/ff/d0/19c420e2e94957895098f294f6f997276e4975f7ea77e991719be4643210/dolmen.app.authentication-1.0b2.tar.gz" } ], "1.0b3": [ { "comment_text": "", "digests": { "md5": "2aa6662e55da090ece78dded58edc032", "sha256": "aefa10638836941efe2ef14206c9c3a2b19d60368f0be63cbecb3e7b750595ac" }, "downloads": -1, "filename": "dolmen.app.authentication-1.0b3.tar.gz", "has_sig": false, "md5_digest": "2aa6662e55da090ece78dded58edc032", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24721, "upload_time": "2010-11-19T14:48:38", "url": "https://files.pythonhosted.org/packages/99/49/d8142a8c12b4892f782e90c36de55f72ecd48b87b24ef5791cecaa01478a/dolmen.app.authentication-1.0b3.tar.gz" } ], "1.0b4": [ { "comment_text": "", "digests": { "md5": "6bb246ffe640afe225611550f81c79c2", "sha256": "9968b215bad564798669b202a337b1f2c61c59dc50f272ebf5f7aaf2256b0c40" }, "downloads": -1, "filename": "dolmen.app.authentication-1.0b4.tar.gz", "has_sig": false, "md5_digest": "6bb246ffe640afe225611550f81c79c2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24746, "upload_time": "2013-10-31T09:47:12", "url": "https://files.pythonhosted.org/packages/c1/01/ce7dd747fdec9ee508f3856bb31579b2febfea7e75b3386510241efc977c/dolmen.app.authentication-1.0b4.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "66de970b052bca7700429bb427e33f05", "sha256": "20997cdb832dcb216bfc9ad93a88e1ea3330971d50f11a6db21eb18fc3ce8d23" }, "downloads": -1, "filename": "dolmen.app.authentication-1.1.tar.gz", "has_sig": false, "md5_digest": "66de970b052bca7700429bb427e33f05", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24457, "upload_time": "2013-11-06T17:01:07", "url": "https://files.pythonhosted.org/packages/d6/8b/39259c10b6e7834c0084d23021055c169e16f369a6dd8addf2005f06a87f/dolmen.app.authentication-1.1.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "22cb5beae1c3d5dec6833944e2f23fc5", "sha256": "0a75c1167c7e26c60bddb2ca123b511b15f52368c4d1c7f62268bf9069aa96fc" }, "downloads": -1, "filename": "dolmen.app.authentication-1.1.1.tar.gz", "has_sig": false, "md5_digest": "22cb5beae1c3d5dec6833944e2f23fc5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24509, "upload_time": "2013-11-11T13:47:48", "url": "https://files.pythonhosted.org/packages/bb/f0/ec7a4fbf12409c47ed044ed708579214a5ad97f1f205e4d62ef7399ea6d8/dolmen.app.authentication-1.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "22cb5beae1c3d5dec6833944e2f23fc5", "sha256": "0a75c1167c7e26c60bddb2ca123b511b15f52368c4d1c7f62268bf9069aa96fc" }, "downloads": -1, "filename": "dolmen.app.authentication-1.1.1.tar.gz", "has_sig": false, "md5_digest": "22cb5beae1c3d5dec6833944e2f23fc5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 24509, "upload_time": "2013-11-11T13:47:48", "url": "https://files.pythonhosted.org/packages/bb/f0/ec7a4fbf12409c47ed044ed708579214a5ad97f1f205e4d62ef7399ea6d8/dolmen.app.authentication-1.1.1.tar.gz" } ] }