[Checkins] SVN: zope.pluggableauth/trunk/src/zope/pluggableauth/ The modified module does no longer need the separate doctests.
Souheil CHELFOUH
souheil at chelfouh.com
Sun Jan 24 13:42:15 EST 2010
Log message for revision 108444:
The modified module does no longer need the separate doctests.
Only the needed factories have been preserved.
The PrincipalFolder and InternalPrincipal-related component have been terminated.
Changed:
U zope.pluggableauth/trunk/src/zope/pluggableauth/factories.py
D zope.pluggableauth/trunk/src/zope/pluggableauth/factories.txt
U zope.pluggableauth/trunk/src/zope/pluggableauth/interfaces.py
-=-
Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/factories.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/factories.py 2010-01-24 18:36:39 UTC (rev 108443)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/factories.py 2010-01-24 18:42:15 UTC (rev 108444)
@@ -11,173 +11,20 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""ZODB-based Authentication Source
+"""Principals related factories
$Id$
"""
__docformat__ = "reStructuredText"
-from persistent import Persistent
-from zope import interface
from zope import component
+from zope import interface
+from zope.authentication.interfaces import IAuthentication
from zope.event import notify
-from zope.schema import Text, TextLine, Password, Choice
+from zope.pluggableauth import interfaces
from zope.publisher.interfaces import IRequest
-from zope.authentication.interfaces import IAuthentication
-from zope.container.interfaces import DuplicateIDError
-from zope.container.contained import Contained
-from zope.container.constraints import contains, containers
-from zope.container.btree import BTreeContainer
-from zope.password.interfaces import IPasswordManager
-from zope.app.authentication.i18n import ZopeMessageFactory as _
-from zope.app.authentication import interfaces
-
-
-class IInternalPrincipal(interface.Interface):
- """Principal information"""
-
- login = TextLine(
- title=_("Login"),
- description=_("The Login/Username of the principal. "
- "This value can change."))
-
- def setPassword(password, passwordManagerName=None):
- pass
-
- password = Password(
- title=_("Password"),
- description=_("The password for the principal."))
-
- passwordManagerName = Choice(
- title=_("Password Manager"),
- vocabulary="Password Manager Names",
- description=_("The password manager will be used"
- " for encode/check the password"),
- default="SSHA",
- # TODO: The password manager name may be changed only
- # if the password changed
- readonly=True
- )
-
- title = TextLine(
- title=_("Title"),
- description=_("Provides a title for the principal."))
-
- description = Text(
- title=_("Description"),
- description=_("Provides a description for the principal."),
- required=False,
- missing_value='',
- default=u'')
-
-
-class IInternalPrincipalContainer(interface.Interface):
- """A container that contains internal principals."""
-
- prefix = TextLine(
- title=_("Prefix"),
- description=_(
- "Prefix to be added to all principal ids to assure "
- "that all ids are unique within the authentication service"),
- missing_value=u"",
- default=u'',
- readonly=True)
-
- def getIdByLogin(login):
- """Return the principal id currently associated with login.
-
- The return value includes the container prefix, but does not
- include the PAU prefix.
-
- KeyError is raised if no principal is associated with login.
-
- """
-
- contains(IInternalPrincipal)
-
-
-class IInternalPrincipalContained(interface.Interface):
- """Principal information"""
-
- containers(IInternalPrincipalContainer)
-
-
-class ISearchSchema(interface.Interface):
- """Search Interface for this Principal Provider"""
-
- search = TextLine(
- title=_("Search String"),
- description=_("A Search String"),
- required=False,
- default=u'',
- missing_value=u'')
-
-
-class InternalPrincipal(Persistent, Contained):
- """An internal principal for Persistent Principal Folder."""
-
- interface.implements(IInternalPrincipal, IInternalPrincipalContained)
-
- # If you're searching for self._passwordManagerName, or self._password
- # probably you just need to evolve the database to new generation
- # at /++etc++process/@@generations.html
-
- # NOTE: All changes needs to be synchronized with the evolver at
- # zope.app.zopeappgenerations.evolve2
-
- def __init__(self, login, password, title, description=u'',
- passwordManagerName="SSHA"):
- self._login = login
- self._passwordManagerName = passwordManagerName
- self.password = password
- self.title = title
- self.description = description
-
- def getPasswordManagerName(self):
- return self._passwordManagerName
-
- passwordManagerName = property(getPasswordManagerName)
-
- def _getPasswordManager(self):
- return component.getUtility(
- IPasswordManager, self.passwordManagerName)
-
- def getPassword(self):
- return self._password
-
- def setPassword(self, password, passwordManagerName=None):
- if passwordManagerName is not None:
- self._passwordManagerName = passwordManagerName
- passwordManager = self._getPasswordManager()
- self._password = passwordManager.encodePassword(password)
-
- password = property(getPassword, setPassword)
-
- def checkPassword(self, password):
- passwordManager = self._getPasswordManager()
- return passwordManager.checkPassword(self.password, password)
-
- def getPassword(self):
- return self._password
-
- def getLogin(self):
- return self._login
-
- def setLogin(self, login):
- oldLogin = self._login
- self._login = login
- if self.__parent__ is not None:
- try:
- self.__parent__.notifyLoginChanged(oldLogin, self)
- except ValueError:
- self._login = oldLogin
- raise
-
- login = property(getLogin, setLogin)
-
-
class PrincipalInfo(object):
"""An implementation of IPrincipalInfo used by the principal folder.
@@ -208,116 +55,6 @@
return 'PrincipalInfo(%r)' % self.id
-class PrincipalFolder(BTreeContainer):
- """A Persistent Principal Folder and Authentication plugin.
-
- See principalfolder.txt for details.
- """
-
- interface.implements(interfaces.IAuthenticatorPlugin,
- interfaces.IQuerySchemaSearch,
- IInternalPrincipalContainer)
-
- schema = ISearchSchema
-
- def __init__(self, prefix=''):
- self.prefix = unicode(prefix)
- super(PrincipalFolder, self).__init__()
- self.__id_by_login = self._newContainerData()
-
- def notifyLoginChanged(self, oldLogin, principal):
- """Notify the Container about changed login of a principal.
-
- We need this, so that our second tree can be kept up-to-date.
- """
- # A user with the new login already exists
- if principal.login in self.__id_by_login:
- raise ValueError('Principal Login already taken!')
-
- del self.__id_by_login[oldLogin]
- self.__id_by_login[principal.login] = principal.__name__
-
- def __setitem__(self, id, principal):
- """Add principal information.
-
- Create a Principal Folder
-
- >>> pf = PrincipalFolder()
-
- Create a principal with 1 as id
- Add a login attr since __setitem__ is in need of one
-
- >>> principal = Principal(1)
- >>> principal.login = 1
-
- Add the principal within the Principal Folder
-
- >>> pf.__setitem__(u'1', principal)
-
- Try to add another principal with the same id.
- It should raise a DuplicateIDError
-
- >>> try:
- ... pf.__setitem__(u'1', principal)
- ... except DuplicateIDError, e:
- ... pass
- >>>
- """
- # A user with the new login already exists
- if principal.login in self.__id_by_login:
- raise DuplicateIDError('Principal Login already taken!')
-
- super(PrincipalFolder, self).__setitem__(id, principal)
- self.__id_by_login[principal.login] = id
-
- def __delitem__(self, id):
- """Remove principal information."""
- principal = self[id]
- super(PrincipalFolder, self).__delitem__(id)
- del self.__id_by_login[principal.login]
-
- def authenticateCredentials(self, credentials):
- """Return principal info if credentials can be authenticated
- """
- if not isinstance(credentials, dict):
- return None
- if not ('login' in credentials and 'password' in credentials):
- return None
- id = self.__id_by_login.get(credentials['login'])
- if id is None:
- return None
- internal = self[id]
- if not internal.checkPassword(credentials["password"]):
- return None
- return PrincipalInfo(self.prefix + id, internal.login, internal.title,
- internal.description)
-
- def principalInfo(self, id):
- if id.startswith(self.prefix):
- internal = self.get(id[len(self.prefix):])
- if internal is not None:
- return PrincipalInfo(id, internal.login, internal.title,
- internal.description)
-
- def getIdByLogin(self, login):
- return self.prefix + self.__id_by_login[login]
-
- def search(self, query, start=None, batch_size=None):
- """Search through this principal provider."""
- search = query.get('search')
- if search is None:
- return
- search = search.lower()
- n = 1
- for i, value in enumerate(self.values()):
- if (search in value.title.lower() or
- search in value.description.lower() or
- search in value.login.lower()):
- if not ((start is not None and i < start)
- or (batch_size is not None and n > batch_size)):
- n += 1
- yield self.prefix + value.__name__
-
class Principal(object):
"""A group-aware implementation of zope.security.interfaces.IPrincipal.
@@ -440,6 +177,7 @@
group = principals.getPrincipal(group_id)
stack.append(iter(group.groups))
+
class AuthenticatedPrincipalFactory(object):
"""Creates 'authenticated' principals.
Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/factories.txt
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/factories.txt 2010-01-24 18:36:39 UTC (rev 108443)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/factories.txt 2010-01-24 18:42:15 UTC (rev 108444)
@@ -1,170 +0,0 @@
-================
-Principal Folder
-================
-
-Principal folders contain principal-information objects that contain principal
-information. We create an internal principal using the `InternalPrincipal`
-class:
-
- >>> from zope.app.authentication.principalfolder import InternalPrincipal
- >>> p1 = InternalPrincipal('login1', '123', "Principal 1",
- ... passwordManagerName="SHA1")
- >>> p2 = InternalPrincipal('login2', '456', "The Other One")
-
-and add them to a principal folder:
-
- >>> from zope.app.authentication.principalfolder import PrincipalFolder
- >>> principals = PrincipalFolder('principal.')
- >>> principals['p1'] = p1
- >>> principals['p2'] = p2
-
-Authentication
---------------
-
-Principal folders provide the `IAuthenticatorPlugin` interface. When we
-provide suitable credentials:
-
- >>> from zope.testing.doctestunit import pprint
- >>> principals.authenticateCredentials({'login': 'login1', 'password': '123'})
- PrincipalInfo(u'principal.p1')
-
-We get back a principal id and supplementary information, including the
-principal title and description. Note that the principal id is a concatenation
-of the principal-folder prefix and the name of the principal-information object
-within the folder.
-
-None is returned if the credentials are invalid:
-
- >>> principals.authenticateCredentials({'login': 'login1',
- ... 'password': '1234'})
- >>> principals.authenticateCredentials(42)
-
-Search
-------
-
-Principal folders also provide the IQuerySchemaSearch interface. This
-supports both finding principal information based on their ids:
-
- >>> principals.principalInfo('principal.p1')
- PrincipalInfo('principal.p1')
-
- >>> principals.principalInfo('p1')
-
-and searching for principals based on a search string:
-
- >>> list(principals.search({'search': 'other'}))
- [u'principal.p2']
-
- >>> list(principals.search({'search': 'OTHER'}))
- [u'principal.p2']
-
- >>> list(principals.search({'search': ''}))
- [u'principal.p1', u'principal.p2']
-
- >>> list(principals.search({'search': 'eek'}))
- []
-
- >>> list(principals.search({}))
- []
-
-If there are a large number of matches:
-
- >>> for i in range(20):
- ... i = str(i)
- ... p = InternalPrincipal('l'+i, i, "Dude "+i)
- ... principals[i] = p
-
- >>> pprint(list(principals.search({'search': 'D'})))
- [u'principal.0',
- u'principal.1',
- u'principal.10',
- u'principal.11',
- u'principal.12',
- u'principal.13',
- u'principal.14',
- u'principal.15',
- u'principal.16',
- u'principal.17',
- u'principal.18',
- u'principal.19',
- u'principal.2',
- u'principal.3',
- u'principal.4',
- u'principal.5',
- u'principal.6',
- u'principal.7',
- u'principal.8',
- u'principal.9']
-
-We can use batching parameters to specify a subset of results:
-
- >>> pprint(list(principals.search({'search': 'D'}, start=17)))
- [u'principal.7',
- u'principal.8',
- u'principal.9']
-
- >>> pprint(list(principals.search({'search': 'D'}, batch_size=5)))
- [u'principal.0',
- u'principal.1',
- u'principal.10',
- u'principal.11',
- u'principal.12']
-
- >>> pprint(list(principals.search({'search': 'D'}, start=5, batch_size=5)))
- [u'principal.13',
- u'principal.14',
- u'principal.15',
- u'principal.16',
- u'principal.17']
-
-There is an additional method that allows requesting the principal id
-associated with a login id. The method raises KeyError when there is
-no associated principal::
-
- >>> principals.getIdByLogin("not-there")
- Traceback (most recent call last):
- KeyError: 'not-there'
-
-If there is a matching principal, the id is returned::
-
- >>> principals.getIdByLogin("login1")
- u'principal.p1'
-
-Changing credentials
---------------------
-
-Credentials can be changed by modifying principal-information objects:
-
- >>> p1.login = 'bob'
- >>> p1.password = 'eek'
-
- >>> principals.authenticateCredentials({'login': 'bob', 'password': 'eek'})
- PrincipalInfo(u'principal.p1')
-
- >>> principals.authenticateCredentials({'login': 'login1',
- ... 'password': 'eek'})
-
- >>> principals.authenticateCredentials({'login': 'bob',
- ... 'password': '123'})
-
-
-It is an error to try to pick a login name that is already taken:
-
- >>> p1.login = 'login2'
- Traceback (most recent call last):
- ...
- ValueError: Principal Login already taken!
-
-If such an attempt is made, the data are unchanged:
-
- >>> principals.authenticateCredentials({'login': 'bob', 'password': 'eek'})
- PrincipalInfo(u'principal.p1')
-
-Removing principals
--------------------
-
-Of course, if a principal is removed, we can no-longer authenticate it:
-
- >>> del principals['p1']
- >>> principals.authenticateCredentials({'login': 'bob',
- ... 'password': 'eek'})
Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/interfaces.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/interfaces.py 2010-01-24 18:36:39 UTC (rev 108443)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/interfaces.py 2010-01-24 18:42:15 UTC (rev 108444)
@@ -20,7 +20,6 @@
import zope.interface
from zope.i18nmessageid import MessageFactory
from zope.authentication.interfaces import ILogout
-from zope.schema import Choice, List, TextLine
from zope.container.constraints import contains, containers
from zope.container.interfaces import IContainer
More information about the checkins
mailing list