diff --git a/organize/README.txt b/organize/README.txt
index 68b8f8b..a97a541 100644
--- a/organize/README.txt
+++ b/organize/README.txt
@@ -33,8 +33,9 @@ ZCML setup):
>>> person = concepts['person']
>>> from loops.concept import Concept
- >>> johnC = concepts['john'] = Concept(u'John')
- >>> johnC.conceptType = person
+ >>> from loops.setup import addAndConfigureObject
+ >>> johnC = addAndConfigureObject(concepts, Concept, 'john', title=u'John',
+ ... conceptType=person)
Organizations: Persons (and Users), Institutions, Addresses...
@@ -237,6 +238,18 @@ The person-based authenticator provides authentication without having to
store a persistent (internal) principal object.
>>> from loops.organize.auth import PersonBasedAuthenticator
+ >>> pbAuth = PersonBasedAuthenticator('persons.')
+ >>> pau['persons'] = pbAuth
+ >>> pau.authenticatorPlugins = ('loops', 'persons',)
+
+ >>> eddieC = addAndConfigureObject(concepts, Concept, 'eddie', title=u'Eddie',
+ ... conceptType=person)
+ >>> eddie = adapted(eddieC)
+ >>> eddie.userId = 'persons.eddie'
+
+ >>> pbAuth.setPassword('eddie', 'secret')
+ >>> pbAuth.authenticateCredentials(dict(login='eddie', password='secret'))
+ PrincipalInfo(u'persons.eddie')
Security
@@ -332,7 +345,6 @@ Tasks and Events
Task view with edit action
--------------------------
- >>> from loops.setup import addAndConfigureObject
>>> from loops.organize.interfaces import ITask
>>> task = addAndConfigureObject(concepts, Concept, 'task', title=u'Task',
... conceptType=type, typeInterface=ITask)
@@ -399,7 +411,7 @@ Send Email to Members
>>> form.subject
u"loops Notification from '$site'"
>>> form.mailBody
- u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.target95\n\n'
+ u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.target97\n\n'
Fin de partie
diff --git a/organize/auth.py b/organize/auth.py
index c87c677..fa50f01 100644
--- a/organize/auth.py
+++ b/organize/auth.py
@@ -25,17 +25,34 @@ $Id$
from persistent import Persistent
from zope.app.container.contained import Contained
from zope import component
-from zope.interface import implements
+from zope.interface import Interface, implements
from zope.app.authentication.interfaces import IAuthenticatorPlugin
from zope.app.authentication.principalfolder import PrincipalInfo
from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
from zope.app.security.interfaces import IAuthentication
-from zope.cachedescriptors.property import Lazy
+from zope import schema
+from zope.traversing.api import getParent
+
+from loops.util import _
+
+
+class IPersonBasedAuthenticator(Interface):
+
+ prefix = schema.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)
class PersonBasedAuthenticator(Persistent, Contained):
- implements(IAuthenticatorPlugin)
+ implements(IAuthenticatorPlugin, IPersonBasedAuthenticator)
+
+ passwordKey = 'loops.organize.password'
def __init__(self, prefix=''):
self.prefix = unicode(prefix)
@@ -45,11 +62,8 @@ class PersonBasedAuthenticator(Persistent, Contained):
return None
login = credentials.get('login')
password = credentials.get('password')
- if not login or not password :
- return None
- id = self.prefix + login
- if self._checkPassword(id, password):
- return PrincipalInfo(id, login, login, u'')
+ if self.checkPassword(login, password):
+ return PrincipalInfo(self.prefix + login, login, login, u'')
return None
def principalInfo(self, id):
@@ -58,19 +72,35 @@ class PersonBasedAuthenticator(Persistent, Contained):
if login:
return PrincipalInfo(id, login, login, u'')
+ def checkPassword(self, login, password):
+ if login and password:
+ pa = self.getPrincipalAnnotations(
+ getParent(self).prefix + self.prefix + login)
+ return pa.get(self.passwordKey) == password
+ return None
+
def setPassword(self, login, password):
- id = self.prefix + login
- pa = self.getPrincipalAnnotations(id)
- pa['loops.organize.password'] = password
+ pa = self.getPrincipalAnnotations(
+ getParent(self).prefix + self.prefix + login)
+ pa[self.passwordKey] = password
- @Lazy
- def principalAnnotations(self):
- return component.getUtility(IPrincipalAnnotationUtility)
+ def getPrincipalAnnotations(self, id):
+ utility = component.getUtility(IPrincipalAnnotationUtility)
+ return utility.getAnnotationsById(id)
- def getPrincipalAnnotations(id):
- return self.principalAnnotations.getAnnotationsById(id)
+ def get(self, login):
+ return InternalPrincipal(self, login)
- def _checkPassword(self, id, password):
- pa = self.getPrincipalAnnotations(id)
- return pa.get('loops.organize.password') == password
+
+class InternalPrincipal(object):
+
+ def __init__(self, auth, login):
+ self.auth = auth
+ self.login = login
+
+ def checkPassword(self, password):
+ return self.auth.checkPassword(self.login, password)
+
+ def setPassword(self, passowrd):
+ self.auth.setPassword(self.login, password)
diff --git a/organize/browser/configure.zcml b/organize/browser/configure.zcml
index c602c89..2162574 100644
--- a/organize/browser/configure.zcml
+++ b/organize/browser/configure.zcml
@@ -62,4 +62,30 @@
class="loops.organize.browser.party.SendEmailForm"
permission="zope.View" />
+
+
+
+
+
+
+
+
diff --git a/organize/configure.zcml b/organize/configure.zcml
index 1508e5f..2a6c454 100644
--- a/organize/configure.zcml
+++ b/organize/configure.zcml
@@ -48,6 +48,14 @@
interface="loops.organize.interfaces.IMemberRegistrationManager" />
+
+
+
+
+
+