[Checkins] SVN: zope.app.authentication/trunk/ merge -r 117492:117504 svn+ssh://svn.zope.org/repos/main/zope.app.authentication/branches/jw-move-authenticator-plugins
Jan-Wijbrand Kolman
janwijbrand at gmail.com
Mon Oct 18 05:40:32 EDT 2010
Log message for revision 117633:
merge -r 117492:117504 svn+ssh://svn.zope.org/repos/main/zope.app.authentication/branches/jw-move-authenticator-plugins
Changed:
U zope.app.authentication/trunk/CHANGES.txt
U zope.app.authentication/trunk/buildout.cfg
U zope.app.authentication/trunk/setup.py
U zope.app.authentication/trunk/src/zope/app/authentication/configure.zcml
U zope.app.authentication/trunk/src/zope/app/authentication/groupfolder.py
U zope.app.authentication/trunk/src/zope/app/authentication/groupfolder.zcml
U zope.app.authentication/trunk/src/zope/app/authentication/idpicker.py
U zope.app.authentication/trunk/src/zope/app/authentication/interfaces.py
U zope.app.authentication/trunk/src/zope/app/authentication/principalfolder.py
U zope.app.authentication/trunk/src/zope/app/authentication/principalfolder.zcml
-=-
Modified: zope.app.authentication/trunk/CHANGES.txt
===================================================================
--- zope.app.authentication/trunk/CHANGES.txt 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/CHANGES.txt 2010-10-18 09:40:31 UTC (rev 117633)
@@ -5,6 +5,9 @@
3.9 (unreleased)
----------------
+* Move concrete IAuthenticatorPlugin implementations to
+ zope.pluggableauth.plugins. Leave backwards compatibility imports.
+
* Use zope.formlib throughout to lift the dependency on zope.app.form. As it
turns out, zope.app.form is still a indirect test dependency though.
Modified: zope.app.authentication/trunk/buildout.cfg
===================================================================
--- zope.app.authentication/trunk/buildout.cfg 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/buildout.cfg 2010-10-18 09:40:31 UTC (rev 117633)
@@ -1,10 +1,13 @@
[buildout]
extends =
- http://download.zope.org/zopetoolkit/index/1.0c3/ztk-versions.cfg
- http://download.zope.org/zopetoolkit/index/1.0c3/zopeapp-versions.cfg
+ http://download.zope.org/zopetoolkit/index/1.0/ztk-versions.cfg
+ http://download.zope.org/zopetoolkit/index/1.0/zopeapp-versions.cfg
develop = .
parts = test
+[versions]
+zope.pluggableauth = 1.1.0
+
[test]
recipe = zc.recipe.testrunner
eggs = zope.app.authentication [test]
Modified: zope.app.authentication/trunk/setup.py
===================================================================
--- zope.app.authentication/trunk/setup.py 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/setup.py 2010-10-18 09:40:31 UTC (rev 117633)
@@ -87,11 +87,10 @@
'zope.interface',
'zope.location',
'zope.password >= 3.5.1',
- 'zope.pluggableauth >= 1.0.1',
+ 'zope.pluggableauth >= 1.1',
'zope.schema',
'zope.security',
'zope.traversing',
-
# Needed for browser code.
'zope.app.container',
'zope.app.component',
Modified: zope.app.authentication/trunk/src/zope/app/authentication/configure.zcml
===================================================================
--- zope.app.authentication/trunk/src/zope/app/authentication/configure.zcml 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/src/zope/app/authentication/configure.zcml 2010-10-18 09:40:31 UTC (rev 117633)
@@ -56,8 +56,10 @@
<include file="password.zcml" />
<include file="session.zcml" />
<include file="httpplugins.zcml" />
+
<include file="principalfolder.zcml" />
<include file="groupfolder.zcml" />
+
<include file="ftpplugins.zcml" />
<include package=".browser" />
Modified: zope.app.authentication/trunk/src/zope/app/authentication/groupfolder.py
===================================================================
--- zope.app.authentication/trunk/src/zope/app/authentication/groupfolder.py 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/src/zope/app/authentication/groupfolder.py 2010-10-18 09:40:31 UTC (rev 117633)
@@ -16,348 +16,21 @@
$Id$
"""
-import BTrees.OOBTree
-import persistent
-
-from zope import interface, event, schema, component
-from zope.interface import alsoProvides
-from zope.security.interfaces import (
- IGroup, IGroupAwarePrincipal, IMemberAwareGroup)
-
-from zope.container.btree import BTreeContainer
-import zope.container.constraints
-import zope.container.interfaces
-from zope.app.authentication.i18n import ZopeMessageFactory as _
-import zope.authentication.principal
-from zope.authentication.interfaces import (
- IAuthentication, IAuthenticatedGroup, IEveryoneGroup)
-from zope.app.authentication import principalfolder, interfaces
-
-
-class IGroupInformation(interface.Interface):
-
- title = schema.TextLine(
- title=_("Title"),
- description=_("Provides a title for the permission."),
- required=True)
-
- description = schema.Text(
- title=_("Description"),
- description=_("Provides a description for the permission."),
- required=False)
-
- principals = schema.List(
- title=_("Principals"),
- value_type=schema.Choice(
- source=zope.authentication.principal.PrincipalSource()),
- description=_(
- "List of ids of principals which belong to the group"),
- required=False)
-
-
-class IGroupFolder(zope.container.interfaces.IContainer):
-
- zope.container.constraints.contains(IGroupInformation)
-
- prefix = schema.TextLine(
- title=_("Group ID prefix"),
- description=_("Prefix added to IDs of groups in this folder"),
- readonly=True,
- )
-
- def getGroupsForPrincipal(principalid):
- """Get groups the given principal belongs to"""
-
- def getPrincipalsForGroup(groupid):
- """Get principals which belong to the group"""
-
-
-class IGroupContained(zope.container.interfaces.IContained):
-
- zope.container.constraints.containers(IGroupFolder)
-
-class IGroupSearchCriteria(interface.Interface):
-
- search = schema.TextLine(
- title=_("Group Search String"),
- required=False,
- missing_value=u'',
- )
-
-class IGroupPrincipalInfo(interfaces.IPrincipalInfo):
- members = interface.Attribute('an iterable of members of the group')
-
-class GroupInfo(object):
- """An implementation of IPrincipalInfo used by the group folder.
-
- A group info is created with id, title, and description:
-
- >>> class DemoGroupInformation(object):
- ... interface.implements(IGroupInformation)
- ... def __init__(self, title, description, principals):
- ... self.title = title
- ... self.description = description
- ... self.principals = principals
- ...
- >>> i = DemoGroupInformation(
- ... 'Managers', 'Taskmasters', ('joe', 'jane'))
- ...
- >>> info = GroupInfo('groups.managers', i)
- >>> info
- GroupInfo('groups.managers')
- >>> info.id
- 'groups.managers'
- >>> info.title
- 'Managers'
- >>> info.description
- 'Taskmasters'
- >>> info.members
- ('joe', 'jane')
- >>> info.members = ('joe', 'jane', 'jaime')
- >>> info.members
- ('joe', 'jane', 'jaime')
-
- """
- interface.implements(IGroupPrincipalInfo)
-
- def __init__(self, id, information):
- self.id = id
- self._information = information
-
- @property
- def title(self):
- return self._information.title
-
- @property
- def description(self):
- return self._information.description
-
- @apply
- def members():
- def get(self):
- return self._information.principals
- def set(self, value):
- self._information.principals = value
- return property(get, set)
-
- def __repr__(self):
- return 'GroupInfo(%r)' % self.id
-
-
-class GroupFolder(BTreeContainer):
-
- interface.implements(
- interfaces.IAuthenticatorPlugin,
- interfaces.IQuerySchemaSearch,
- IGroupFolder)
-
- schema = IGroupSearchCriteria
-
- def __init__(self, prefix=u''):
- super(GroupFolder, self).__init__()
- self.prefix = prefix
- # __inversemapping is used to map principals to groups
- self.__inverseMapping = BTrees.OOBTree.OOBTree()
-
- def __setitem__(self, name, value):
- BTreeContainer.__setitem__(self, name, value)
- group_id = self._groupid(value)
- self._addPrincipalsToGroup(value.principals, group_id)
- if value.principals:
- event.notify(
- interfaces.PrincipalsAddedToGroup(
- value.principals, self.__parent__.prefix + group_id))
- group = principalfolder.Principal(self.prefix + name)
- event.notify(interfaces.GroupAdded(group))
-
- def __delitem__(self, name):
- value = self[name]
- group_id = self._groupid(value)
- self._removePrincipalsFromGroup(value.principals, group_id)
- if value.principals:
- event.notify(
- interfaces.PrincipalsRemovedFromGroup(
- value.principals, self.__parent__.prefix + group_id))
- BTreeContainer.__delitem__(self, name)
-
- def _groupid(self, group):
- return self.prefix+group.__name__
-
- def _addPrincipalsToGroup(self, principal_ids, group_id):
- for principal_id in principal_ids:
- self.__inverseMapping[principal_id] = (
- self.__inverseMapping.get(principal_id, ())
- + (group_id,))
-
- def _removePrincipalsFromGroup(self, principal_ids, group_id):
- for principal_id in principal_ids:
- groups = self.__inverseMapping.get(principal_id)
- if groups is None:
- return
- new = tuple([id for id in groups if id != group_id])
- if new:
- self.__inverseMapping[principal_id] = new
- else:
- del self.__inverseMapping[principal_id]
-
- def getGroupsForPrincipal(self, principalid):
- """Get groups the given principal belongs to"""
- return self.__inverseMapping.get(principalid, ())
-
- def getPrincipalsForGroup(self, groupid):
- """Get principals which belong to the group"""
- return self[groupid].principals
-
- def search(self, query, start=None, batch_size=None):
- """ Search for groups"""
- search = query.get('search')
- if search is not None:
- n = 0
- search = search.lower()
- for i, (id, groupinfo) in enumerate(self.items()):
- if (search in groupinfo.title.lower() or
- (groupinfo.description and
- search in groupinfo.description.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 + id
-
- def authenticateCredentials(self, credentials):
- # user folders don't authenticate
- pass
-
- def principalInfo(self, id):
- if id.startswith(self.prefix):
- id = id[len(self.prefix):]
- info = self.get(id)
- if info is not None:
- return GroupInfo(
- self.prefix+id, info)
-
-class GroupCycle(Exception):
- """There is a cyclic relationship among groups
- """
-
-class InvalidPrincipalIds(Exception):
- """A user has a group id for a group that can't be found
- """
-
-class InvalidGroupId(Exception):
- """A user has a group id for a group that can't be found
- """
-
-def nocycles(principal_ids, seen, getPrincipal):
- for principal_id in principal_ids:
- if principal_id in seen:
- raise GroupCycle(principal_id, seen)
- seen.append(principal_id)
- principal = getPrincipal(principal_id)
- nocycles(principal.groups, seen, getPrincipal)
- seen.pop()
-
-class GroupInformation(persistent.Persistent):
-
- interface.implements(IGroupInformation, IGroupContained)
-
- __parent__ = __name__ = None
-
- _principals = ()
-
- def __init__(self, title='', description=''):
- self.title = title
- self.description = description
-
- def setPrincipals(self, prinlist, check=True):
- # method is not a part of the interface
- parent = self.__parent__
- old = self._principals
- self._principals = tuple(prinlist)
-
- if parent is not None:
- oldset = set(old)
- new = set(prinlist)
- group_id = parent._groupid(self)
- removed = oldset - new
- added = new - oldset
- try:
- parent._removePrincipalsFromGroup(removed, group_id)
- except AttributeError:
- removed = None
-
- try:
- parent._addPrincipalsToGroup(added, group_id)
- except AttributeError:
- added = None
-
- if check:
- try:
- principalsUtility = component.getUtility(IAuthentication)
- nocycles(new, [], principalsUtility.getPrincipal)
- except GroupCycle:
- # abort
- self.setPrincipals(old, False)
- raise
- # now that we've gotten past the checks, fire the events.
- if removed:
- event.notify(
- interfaces.PrincipalsRemovedFromGroup(
- removed, self.__parent__.__parent__.prefix + group_id))
- if added:
- event.notify(
- interfaces.PrincipalsAddedToGroup(
- added, self.__parent__.__parent__.prefix + group_id))
-
- principals = property(lambda self: self._principals, setPrincipals)
-
-
-def specialGroups(event):
- principal = event.principal
- if (IGroup.providedBy(principal) or
- not IGroupAwarePrincipal.providedBy(principal)):
- return
-
- everyone = component.queryUtility(IEveryoneGroup)
- if everyone is not None:
- principal.groups.append(everyone.id)
-
- auth = component.queryUtility(IAuthenticatedGroup)
- if auth is not None:
- principal.groups.append(auth.id)
-
-
-def setGroupsForPrincipal(event):
- """Set group information when a principal is created"""
-
- principal = event.principal
- if not IGroupAwarePrincipal.providedBy(principal):
- return
-
- authentication = event.authentication
-
- for name, plugin in authentication.getAuthenticatorPlugins():
- if not IGroupFolder.providedBy(plugin):
- continue
- groupfolder = plugin
- principal.groups.extend(
- [authentication.prefix + id
- for id in groupfolder.getGroupsForPrincipal(principal.id)
- ])
- id = principal.id
- prefix = authentication.prefix + groupfolder.prefix
- if id.startswith(prefix) and id[len(prefix):] in groupfolder:
- alsoProvides(principal, IGroup)
-
- at component.adapter(interfaces.IFoundPrincipalCreated)
-def setMemberSubscriber(event):
- """adds `getMembers`, `setMembers` to groups made from IGroupPrincipalInfo.
- """
- info = event.info
- if IGroupPrincipalInfo.providedBy(info):
- principal = event.principal
- principal.getMembers = lambda : info.members
- def setMembers(value):
- info.members = value
- principal.setMembers = setMembers
- alsoProvides(principal, IMemberAwareGroup)
+# BBB using zope.pluggableauth.plugin.groupfolder
+from zope.pluggableauth.plugins.groupfolder import (
+ GroupCycle,
+ GroupFolder,
+ GroupInfo,
+ GroupInformation,
+ IGroupContained,
+ IGroupFolder,
+ IGroupInformation,
+ IGroupPrincipalInfo,
+ IGroupSearchCriteria,
+ InvalidGroupId,
+ InvalidPrincipalIds,
+ nocycles,
+ setGroupsForPrincipal,
+ setMemberSubscriber,
+ specialGroups,
+ )
Modified: zope.app.authentication/trunk/src/zope/app/authentication/groupfolder.zcml
===================================================================
--- zope.app.authentication/trunk/src/zope/app/authentication/groupfolder.zcml 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/src/zope/app/authentication/groupfolder.zcml 2010-10-18 09:40:31 UTC (rev 117633)
@@ -1,65 +1,47 @@
<configure
- xmlns="http://namespaces.zope.org/zope"
- i18n_domain="zope"
- >
+ xmlns="http://namespaces.zope.org/zope"
+ i18n_domain="zope"
+ >
+ <include package="zope.pluggableauth.plugins" file="groupfolder.zcml" />
+
<class class=".groupfolder.GroupInformation">
<implements
- interface="zope.annotation.interfaces.IAttributeAnnotatable"
- />
+ interface="zope.annotation.interfaces.IAttributeAnnotatable"
+ />
<require
- permission="zope.ManageServices"
- interface=".groupfolder.IGroupInformation
- .groupfolder.IGroupContained"
- set_schema=".groupfolder.IGroupInformation"
- />
+ permission="zope.ManageServices"
+ interface=".groupfolder.IGroupInformation
+ .groupfolder.IGroupContained"
+ set_schema=".groupfolder.IGroupInformation"
+ />
</class>
<class class=".groupfolder.GroupFolder">
<implements
- interface=".groupfolder.IGroupFolder"
- />
+ interface=".groupfolder.IGroupFolder"
+ />
<require
- permission="zope.ManageServices"
- interface="zope.container.interfaces.IContainer
- zope.container.interfaces.INameChooser"
- />
+ permission="zope.ManageServices"
+ interface="zope.container.interfaces.IContainer
+ zope.container.interfaces.INameChooser"
+ />
</class>
- <adapter
- provides="zope.container.interfaces.INameChooser"
- for=".groupfolder.IGroupFolder"
- factory=".idpicker.IdPicker"
- />
-
- <subscriber
- for=".interfaces.IPrincipalCreated"
- handler=".groupfolder.specialGroups"
- />
-
- <subscriber
- for=".interfaces.IPrincipalCreated"
- handler=".groupfolder.setGroupsForPrincipal"
- />
-
- <subscriber
- handler=".groupfolder.setMemberSubscriber"
- />
-
<include package=".browser" file="groupfolder.zcml" />
<!-- Registering documentation with API doc -->
<configure
- xmlns:apidoc="http://namespaces.zope.org/apidoc"
- xmlns:zcml="http://namespaces.zope.org/zcml"
- zcml:condition="have apidoc">
+ xmlns:apidoc="http://namespaces.zope.org/apidoc"
+ xmlns:zcml="http://namespaces.zope.org/zcml"
+ zcml:condition="have apidoc">
<apidoc:bookchapter
- id="groupfolder"
- title="Group Folders"
- doc_path="groupfolder.txt"
- parent="security/authentication"
- />
+ id="groupfolder"
+ title="Group Folders"
+ doc_path="groupfolder.txt"
+ parent="security/authentication"
+ />
</configure>
Modified: zope.app.authentication/trunk/src/zope/app/authentication/idpicker.py
===================================================================
--- zope.app.authentication/trunk/src/zope/app/authentication/idpicker.py 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/src/zope/app/authentication/idpicker.py 2010-10-18 09:40:31 UTC (rev 117633)
@@ -18,93 +18,5 @@
"""
__docformat__ = 'restructuredtext'
-import re
-from zope.exceptions.interfaces import UserError
-from zope.container.contained import NameChooser
-from zope.app.authentication.i18n import ZopeMessageFactory as _
-
-ok = re.compile('[!-~]+$').match
-class IdPicker(NameChooser):
- """Helper base class that picks principal ids.
-
- Add numbers to ids given by users to make them unique.
-
- The Id picker is a variation on the name chooser that picks numeric
- ids when no name is given.
-
- >>> from zope.app.authentication.idpicker import IdPicker
- >>> IdPicker({}).chooseName('', None)
- u'1'
-
- >>> IdPicker({'1': 1}).chooseName('', None)
- u'2'
-
- >>> IdPicker({'2': 1}).chooseName('', None)
- u'1'
-
- >>> IdPicker({'1': 1}).chooseName('bob', None)
- u'bob'
-
- >>> IdPicker({'bob': 1}).chooseName('bob', None)
- u'bob1'
-
- """
- def chooseName(self, name, object):
- i = 0
- name = unicode(name)
- orig = name
- while (not name) or (name in self.context):
- i += 1
- name = orig+str(i)
-
- self.checkName(name, object)
- return name
-
- def checkName(self, name, object):
- """Limit ids
-
- Ids can only contain printable, non-space, 7-bit ASCII strings:
-
- >>> from zope.app.authentication.idpicker import IdPicker
- >>> IdPicker({}).checkName(u'1', None)
- True
-
- >>> IdPicker({}).checkName(u'bob', None)
- True
-
- >>> try:
- ... IdPicker({}).checkName(u'bob\xfa', None)
- ... except UserError, e:
- ... print e
- ... # doctest: +NORMALIZE_WHITESPACE
- Ids must contain only printable 7-bit non-space ASCII characters
-
- >>> try:
- ... IdPicker({}).checkName(u'big bob', None)
- ... except UserError, e:
- ... print e
- ... # doctest: +NORMALIZE_WHITESPACE
- Ids must contain only printable 7-bit non-space ASCII characters
-
- Ids also can't be over 100 characters long:
-
- >>> IdPicker({}).checkName(u'x' * 100, None)
- True
-
- >>> IdPicker({}).checkName(u'x' * 101, None)
- Traceback (most recent call last):
- ...
- UserError: Ids can't be more than 100 characters long.
-
- """
- NameChooser.checkName(self, name, object)
- if not ok(name):
- raise UserError(
- _("Ids must contain only printable 7-bit non-space"
- " ASCII characters")
- )
- if len(name) > 100:
- raise UserError(
- _("Ids can't be more than 100 characters long.")
- )
- return True
+# BBB using zope.pluggableauth.plugins.idpicker
+from zope.pluggableauth.plugins.idpicker import IdPicker
Modified: zope.app.authentication/trunk/src/zope/app/authentication/interfaces.py
===================================================================
--- zope.app.authentication/trunk/src/zope/app/authentication/interfaces.py 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/src/zope/app/authentication/interfaces.py 2010-10-18 09:40:31 UTC (rev 117633)
@@ -27,108 +27,28 @@
# BBB: using zope.pluggableauth
from zope.pluggableauth.interfaces import (
- IPlugin, IAuthenticatorPlugin, ICredentialsPlugin,
- IPluggableAuthentication, IPrincipalInfo,
- IFoundPrincipalFactory, IPrincipalFactory, IAuthenticatedPrincipalFactory,
- IPrincipalCreated, IAuthenticatedPrincipalCreated,
- AuthenticatedPrincipalCreated, IFoundPrincipalCreated,
- FoundPrincipalCreated, IQueriableAuthenticator)
+ AuthenticatedPrincipalCreated,
+ FoundPrincipalCreated,
+ IAuthenticatedPrincipalCreated,
+ IAuthenticatedPrincipalFactory,
+ IAuthenticatorPlugin,
+ ICredentialsPlugin,
+ IFoundPrincipalCreated,
+ IFoundPrincipalFactory,
+ IGroupAdded,
+ IPluggableAuthentication,
+ IPlugin,
+ IPrincipal,
+ IPrincipalCreated,
+ IPrincipalFactory,
+ IPrincipalInfo,
+ IPrincipalsAddedToGroup,
+ IPrincipalsRemovedFromGroup,
+ IQueriableAuthenticator,
+ IQuerySchemaSearch,
+ )
-
-class IPrincipal(zope.security.interfaces.IGroupClosureAwarePrincipal):
-
- groups = zope.schema.List(
- title=_("Groups"),
- description=_(
- """ids of groups to which the principal directly belongs.
-
- Plugins may append to this list. Mutating the list only affects
- the life of the principal object, and does not persist (so
- persistently adding groups to a principal should be done by working
- with a plugin that mutates this list every time the principal is
- created, like the group folder in this package.)
- """),
- value_type=zope.schema.TextLine(),
- required=False)
-
-
-class IQuerySchemaSearch(zope.interface.Interface):
- """An interface for searching using schema-constrained input."""
-
- schema = zope.interface.Attribute("""
- The schema that constrains the input provided to the search method.
-
- A mapping of name/value pairs for each field in this schema is used
- as the query argument in the search method.
- """)
-
- def search(query, start=None, batch_size=None):
- """Returns an iteration of principal IDs matching the query.
-
- query is a mapping of name/value pairs for fields specified by the
- schema.
-
- If the start argument is provided, then it should be an
- integer and the given number of initial items should be
- skipped.
-
- If the batch_size argument is provided, then it should be an
- integer and no more than the given number of items should be
- returned.
- """
-
-
-class IGroupAdded(zope.interface.Interface):
- """A group has been added."""
-
- group = zope.interface.Attribute("""The group that was defined""")
-
-
-class GroupAdded:
- """
- >>> from zope.interface.verify import verifyObject
- >>> event = GroupAdded("group")
- >>> verifyObject(IGroupAdded, event)
- True
- """
-
- zope.interface.implements(IGroupAdded)
-
- def __init__(self, group):
- self.group = group
-
- def __repr__(self):
- return "<GroupAdded %r>" % self.group.id
-
-
-class IPrincipalsAddedToGroup(zope.interface.Interface):
- group_id = zope.interface.Attribute(
- 'the id of the group to which the principal was added')
- principal_ids = zope.interface.Attribute(
- 'an iterable of one or more ids of principals added')
-
-
-class IPrincipalsRemovedFromGroup(zope.interface.Interface):
- group_id = zope.interface.Attribute(
- 'the id of the group from which the principal was removed')
- principal_ids = zope.interface.Attribute(
- 'an iterable of one or more ids of principals removed')
-
-
-class AbstractMembersChanged(object):
-
- def __init__(self, principal_ids, group_id):
- self.principal_ids = principal_ids
- self.group_id = group_id
-
- def __repr__(self):
- return "<%s %r %r>" % (
- self.__class__.__name__, sorted(self.principal_ids), self.group_id)
-
-
-class PrincipalsAddedToGroup(AbstractMembersChanged):
- zope.interface.implements(IPrincipalsAddedToGroup)
-
-
-class PrincipalsRemovedFromGroup(AbstractMembersChanged):
- zope.interface.implements(IPrincipalsRemovedFromGroup)
+# BBB: using zope.pluggableauth
+from zope.pluggableauth.plugins.groupfolder import (
+ GroupAdded,
+ )
Modified: zope.app.authentication/trunk/src/zope/app/authentication/principalfolder.py
===================================================================
--- zope.app.authentication/trunk/src/zope/app/authentication/principalfolder.py 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/src/zope/app/authentication/principalfolder.py 2010-10-18 09:40:31 UTC (rev 117633)
@@ -17,270 +17,20 @@
"""
__docformat__ = "reStructuredText"
-from persistent import Persistent
-from zope.app.authentication.i18n import ZopeMessageFactory as _
-from zope.app.authentication.interfaces import IQuerySchemaSearch
-from zope.component import getUtility
-from zope.container.btree import BTreeContainer
-from zope.container.constraints import contains, containers
-from zope.container.contained import Contained
-from zope.container.interfaces import DuplicateIDError
-from zope.interface import implements, Interface
-from zope.password.interfaces import IPasswordManager
-from zope.schema import Text, TextLine, Password, Choice
-
# BBB using zope.pluggableauth
from zope.pluggableauth.interfaces import IAuthenticatorPlugin
from zope.pluggableauth.factories import (
- Principal, PrincipalInfo,
- FoundPrincipalFactory, AuthenticatedPrincipalFactory)
-
-
-class IInternalPrincipal(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):
- """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):
- """Principal information"""
-
- containers(IInternalPrincipalContainer)
-
-
-class ISearchSchema(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."""
-
- 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 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 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 PrincipalFolder(BTreeContainer):
- """A Persistent Principal Folder and Authentication plugin.
-
- See principalfolder.txt for details.
- """
-
- implements(IAuthenticatorPlugin,
- 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__
+ AuthenticatedPrincipalFactory,
+ FoundPrincipalFactory,
+ Principal,
+ PrincipalInfo,
+ )
+# BBB using zope.pluggableauth.plugins.principalfolder
+from zope.pluggableauth.plugins.principalfolder import (
+ IInternalPrincipal,
+ IInternalPrincipalContained,
+ IInternalPrincipalContainer,
+ InternalPrincipal,
+ ISearchSchema,
+ PrincipalFolder,
+ )
Modified: zope.app.authentication/trunk/src/zope/app/authentication/principalfolder.zcml
===================================================================
--- zope.app.authentication/trunk/src/zope/app/authentication/principalfolder.zcml 2010-10-18 09:32:52 UTC (rev 117632)
+++ zope.app.authentication/trunk/src/zope/app/authentication/principalfolder.zcml 2010-10-18 09:40:31 UTC (rev 117633)
@@ -1,39 +1,29 @@
<configure xmlns="http://namespaces.zope.org/zope" i18n_domain="zope">
- <include package="zope.pluggableauth" file="principalfactories.zcml" />
+ <include package="zope.pluggableauth.plugins" file="principalfolder.zcml" />
<class class=".principalfolder.InternalPrincipal">
<require
- permission="zope.ManageServices"
- interface=".principalfolder.IInternalPrincipal"
- set_schema=".principalfolder.IInternalPrincipal"
- />
+ permission="zope.ManageServices"
+ interface=".principalfolder.IInternalPrincipal"
+ set_schema=".principalfolder.IInternalPrincipal"
+ />
</class>
<class class=".principalfolder.PrincipalFolder">
-
<implements
- interface="zope.annotation.interfaces.IAttributeAnnotatable"
- />
-
+ interface="zope.annotation.interfaces.IAttributeAnnotatable"
+ />
<require
- permission="zope.ManageServices"
- interface="zope.container.interfaces.IContainer"
- />
-
+ permission="zope.ManageServices"
+ interface="zope.container.interfaces.IContainer"
+ />
<require
- permission="zope.ManageServices"
- attributes="prefix"
- />
-
+ permission="zope.ManageServices"
+ attributes="prefix"
+ />
</class>
- <adapter
- provides="zope.container.interfaces.INameChooser"
- for=".principalfolder.IInternalPrincipalContainer"
- factory=".idpicker.IdPicker"
- />
-
<include package=".browser" file="principalfolder.zcml" />
<!-- Registering documentation with API doc -->
More information about the checkins
mailing list