new authenticator plug-in: virtual principals, based on person objects (work in progress)

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3270 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2009-03-09 13:44:04 +00:00
parent 498a099759
commit cc3652db1c
4 changed files with 99 additions and 23 deletions

View file

@ -33,8 +33,9 @@ ZCML setup):
>>> person = concepts['person'] >>> person = concepts['person']
>>> from loops.concept import Concept >>> from loops.concept import Concept
>>> johnC = concepts['john'] = Concept(u'John') >>> from loops.setup import addAndConfigureObject
>>> johnC.conceptType = person >>> johnC = addAndConfigureObject(concepts, Concept, 'john', title=u'John',
... conceptType=person)
Organizations: Persons (and Users), Institutions, Addresses... 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. store a persistent (internal) principal object.
>>> from loops.organize.auth import PersonBasedAuthenticator >>> 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 Security
@ -332,7 +345,6 @@ Tasks and Events
Task view with edit action Task view with edit action
-------------------------- --------------------------
>>> from loops.setup import addAndConfigureObject
>>> from loops.organize.interfaces import ITask >>> from loops.organize.interfaces import ITask
>>> task = addAndConfigureObject(concepts, Concept, 'task', title=u'Task', >>> task = addAndConfigureObject(concepts, Concept, 'task', title=u'Task',
... conceptType=type, typeInterface=ITask) ... conceptType=type, typeInterface=ITask)
@ -399,7 +411,7 @@ Send Email to Members
>>> form.subject >>> form.subject
u"loops Notification from '$site'" u"loops Notification from '$site'"
>>> form.mailBody >>> 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 Fin de partie

View file

@ -25,17 +25,34 @@ $Id$
from persistent import Persistent from persistent import Persistent
from zope.app.container.contained import Contained from zope.app.container.contained import Contained
from zope import component 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.interfaces import IAuthenticatorPlugin
from zope.app.authentication.principalfolder import PrincipalInfo from zope.app.authentication.principalfolder import PrincipalInfo
from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
from zope.app.security.interfaces import IAuthentication 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): class PersonBasedAuthenticator(Persistent, Contained):
implements(IAuthenticatorPlugin) implements(IAuthenticatorPlugin, IPersonBasedAuthenticator)
passwordKey = 'loops.organize.password'
def __init__(self, prefix=''): def __init__(self, prefix=''):
self.prefix = unicode(prefix) self.prefix = unicode(prefix)
@ -45,11 +62,8 @@ class PersonBasedAuthenticator(Persistent, Contained):
return None return None
login = credentials.get('login') login = credentials.get('login')
password = credentials.get('password') password = credentials.get('password')
if not login or not password : if self.checkPassword(login, password):
return None return PrincipalInfo(self.prefix + login, login, login, u'')
id = self.prefix + login
if self._checkPassword(id, password):
return PrincipalInfo(id, login, login, u'')
return None return None
def principalInfo(self, id): def principalInfo(self, id):
@ -58,19 +72,35 @@ class PersonBasedAuthenticator(Persistent, Contained):
if login: if login:
return PrincipalInfo(id, login, login, u'') 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): def setPassword(self, login, password):
id = self.prefix + login pa = self.getPrincipalAnnotations(
pa = self.getPrincipalAnnotations(id) getParent(self).prefix + self.prefix + login)
pa['loops.organize.password'] = password pa[self.passwordKey] = password
@Lazy def getPrincipalAnnotations(self, id):
def principalAnnotations(self): utility = component.getUtility(IPrincipalAnnotationUtility)
return component.getUtility(IPrincipalAnnotationUtility) return utility.getAnnotationsById(id)
def getPrincipalAnnotations(id): def get(self, login):
return self.principalAnnotations.getAnnotationsById(id) return InternalPrincipal(self, login)
def _checkPassword(self, id, password):
pa = self.getPrincipalAnnotations(id) class InternalPrincipal(object):
return pa.get('loops.organize.password') == password
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)

View file

@ -62,4 +62,30 @@
class="loops.organize.browser.party.SendEmailForm" class="loops.organize.browser.party.SendEmailForm"
permission="zope.View" /> permission="zope.View" />
<!-- authentication -->
<browser:addform
schema="loops.organize.auth.IPersonBasedAuthenticator"
label="Add Person-based Authenticator"
content_factory="loops.organize.auth.PersonBasedAuthenticator"
keyword_arguments="prefix"
name="AddPersonBasedAuthenticator.html"
permission="zope.ManageServices"
/>
<browser:addMenuItem
title="Person-based Authenticator"
description="An authentication plugin for loops Persons"
class="loops.organize.auth.PersonBasedAuthenticator"
permission="zope.ManageServices"
view="AddPersonBasedAuthenticator.html" />
<browser:schemadisplay
schema="loops.organize.auth.IPersonBasedAuthenticator"
label="Authenticator Prefix"
name="prefix.html"
fields="prefix"
permission="zope.ManageServices"
menu="zmi_views" title="Prefix" />
</configure> </configure>

View file

@ -48,6 +48,14 @@
interface="loops.organize.interfaces.IMemberRegistrationManager" /> interface="loops.organize.interfaces.IMemberRegistrationManager" />
</zope:class> </zope:class>
<!-- authentication -->
<zope:localUtility class="loops.organize.auth.PersonBasedAuthenticator">
<require
permission="zope.ManageServices"
attributes="prefix" />
</zope:localUtility>
<!-- other adapters --> <!-- other adapters -->
<zope:adapter factory="loops.organize.schema.PersonSchemaFactory" /> <zope:adapter factory="loops.organize.schema.PersonSchemaFactory" />