loops.organize: handling of concept deletion, error checking
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1210 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
966a75f166
commit
60111065e7
3 changed files with 98 additions and 22 deletions
|
@ -14,9 +14,14 @@ Letz's do some basic set up
|
||||||
>>> from zope import component, interface
|
>>> from zope import component, interface
|
||||||
>>> from zope.app import zapi
|
>>> from zope.app import zapi
|
||||||
|
|
||||||
and setup a simple loops site with a concept manager and some concepts:
|
and setup a simple loops site with a concept manager and some concepts
|
||||||
|
(with all the type machinery, what in real life is done via standard
|
||||||
|
ZCML setup):
|
||||||
|
|
||||||
>>> from loops import Loops
|
>>> from loops import Loops
|
||||||
|
>>> from loops.concept import ConceptManager, Concept
|
||||||
|
>>> from loops.interfaces import IConcept, ITypeConcept
|
||||||
|
|
||||||
>>> site['loops'] = Loops()
|
>>> site['loops'] = Loops()
|
||||||
>>> loopsRoot = site['loops']
|
>>> loopsRoot = site['loops']
|
||||||
|
|
||||||
|
@ -25,7 +30,11 @@ and setup a simple loops site with a concept manager and some concepts:
|
||||||
>>> relations = DummyRelationRegistry()
|
>>> relations = DummyRelationRegistry()
|
||||||
>>> component.provideUtility(relations, IRelationRegistry)
|
>>> component.provideUtility(relations, IRelationRegistry)
|
||||||
|
|
||||||
>>> from loops.concept import ConceptManager, Concept
|
>>> from cybertools.typology.interfaces import IType
|
||||||
|
>>> from loops.type import ConceptType, TypeConcept
|
||||||
|
>>> component.provideAdapter(ConceptType, (IConcept,), IType)
|
||||||
|
>>> component.provideAdapter(TypeConcept, (IConcept,), ITypeConcept)
|
||||||
|
|
||||||
>>> loopsRoot['concepts'] = ConceptManager()
|
>>> loopsRoot['concepts'] = ConceptManager()
|
||||||
>>> concepts = loopsRoot['concepts']
|
>>> concepts = loopsRoot['concepts']
|
||||||
|
|
||||||
|
@ -34,9 +43,11 @@ and setup a simple loops site with a concept manager and some concepts:
|
||||||
>>> type = concepts['type']
|
>>> type = concepts['type']
|
||||||
>>> type.conceptType = type
|
>>> type.conceptType = type
|
||||||
|
|
||||||
|
>>> from loops.organize.interfaces import IPerson
|
||||||
>>> concepts['person'] = Concept(u'Person')
|
>>> concepts['person'] = Concept(u'Person')
|
||||||
>>> person = concepts['person']
|
>>> person = concepts['person']
|
||||||
>>> person.conceptType = type
|
>>> person.conceptType = type
|
||||||
|
>>> ITypeConcept(person).typeInterface = IPerson
|
||||||
|
|
||||||
>>> johnC = Concept(u'John')
|
>>> johnC = Concept(u'John')
|
||||||
>>> concepts['john'] = johnC
|
>>> concepts['john'] = johnC
|
||||||
|
@ -48,8 +59,6 @@ Organizations: Persons (and Users), Institutions, Addresses...
|
||||||
|
|
||||||
The classes used in this package are just adapters to IConcept.
|
The classes used in this package are just adapters to IConcept.
|
||||||
|
|
||||||
>>> from loops.interfaces import IConcept
|
|
||||||
>>> from loops.organize.interfaces import IPerson
|
|
||||||
>>> from loops.organize.party import Person
|
>>> from loops.organize.party import Person
|
||||||
>>> component.provideAdapter(Person, (IConcept,), IPerson)
|
>>> component.provideAdapter(Person, (IConcept,), IPerson)
|
||||||
|
|
||||||
|
@ -98,7 +107,8 @@ For testing, we first have to provide the needed utilities and settings
|
||||||
>>> john.userId = 'users.john'
|
>>> john.userId = 'users.john'
|
||||||
|
|
||||||
>>> annotations = principalAnnotations.getAnnotationsById('users.john')
|
>>> annotations = principalAnnotations.getAnnotationsById('users.john')
|
||||||
>>> annotations.get('loops.organize.person') == relations.getUniqueIdForObject(johnC)
|
>>> from loops.organize.party import ANNOTATION_KEY
|
||||||
|
>>> annotations.get(ANNOTATION_KEY) == johnC
|
||||||
True
|
True
|
||||||
|
|
||||||
Change a userId assignment:
|
Change a userId assignment:
|
||||||
|
@ -107,20 +117,54 @@ Change a userId assignment:
|
||||||
>>> john.userId = 'users.johnny'
|
>>> john.userId = 'users.johnny'
|
||||||
|
|
||||||
>>> annotations = principalAnnotations.getAnnotationsById('users.johnny')
|
>>> annotations = principalAnnotations.getAnnotationsById('users.johnny')
|
||||||
>>> annotations.get('loops.organize.person') == relations.getUniqueIdForObject(johnC)
|
>>> annotations.get(ANNOTATION_KEY) == johnC
|
||||||
True
|
True
|
||||||
>>> annotations = principalAnnotations.getAnnotationsById('users.john')
|
>>> annotations = principalAnnotations.getAnnotationsById('users.john')
|
||||||
>>> annotations.get('loops.organize.person') is None
|
>>> annotations.get(ANNOTATION_KEY) is None
|
||||||
True
|
True
|
||||||
|
|
||||||
>>> john.userId = None
|
>>> john.userId = None
|
||||||
>>> annotations = principalAnnotations.getAnnotationsById('users.johnny')
|
>>> annotations = principalAnnotations.getAnnotationsById('users.johnny')
|
||||||
>>> annotations.get('loops.organize.person') is None
|
>>> annotations.get(ANNOTATION_KEY) is None
|
||||||
True
|
True
|
||||||
|
|
||||||
Deleting a person with a userId assigned removes the corresponding
|
Deleting a person with a userId assigned removes the corresponding
|
||||||
principal annotation:
|
principal annotation:
|
||||||
|
|
||||||
|
>>> from zope.app.container.interfaces import IObjectRemovedEvent
|
||||||
|
>>> from zope.app.container.contained import ObjectRemovedEvent
|
||||||
|
>>> from zope.event import notify
|
||||||
|
>>> from zope.interface import Interface
|
||||||
|
>>> from loops.organize.party import removePersonReferenceFromPrincipal
|
||||||
|
>>> from zope.app.testing import ztapi
|
||||||
|
>>> ztapi.subscribe([IConcept, IObjectRemovedEvent], None,
|
||||||
|
... removePersonReferenceFromPrincipal)
|
||||||
|
|
||||||
|
>>> john.userId = 'users.john'
|
||||||
|
>>> annotations = principalAnnotations.getAnnotationsById('users.john')
|
||||||
|
>>> annotations.get(ANNOTATION_KEY) == johnC
|
||||||
|
True
|
||||||
|
|
||||||
|
>>> del concepts['john']
|
||||||
|
>>> annotations = principalAnnotations.getAnnotationsById('users.john')
|
||||||
|
>>> annotations.get(ANNOTATION_KEY) is None
|
||||||
|
True
|
||||||
|
|
||||||
|
If we try to assign a userId of a principal that already has a person
|
||||||
|
concept assigned we should get an error:
|
||||||
|
|
||||||
|
>>> john.userId = 'users.john'
|
||||||
|
|
||||||
|
>>> marthaC = Concept(u'Martha')
|
||||||
|
>>> concepts['martha'] = marthaC
|
||||||
|
>>> marthaC.conceptType = person
|
||||||
|
>>> martha = IPerson(marthaC)
|
||||||
|
|
||||||
|
>>> martha.userId = 'users.john'
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: ...
|
||||||
|
|
||||||
|
|
||||||
Fin de partie
|
Fin de partie
|
||||||
=============
|
=============
|
||||||
|
|
|
@ -19,4 +19,10 @@
|
||||||
set_schema="loops.organize.interfaces.IPerson" />
|
set_schema="loops.organize.interfaces.IPerson" />
|
||||||
</zope:class>
|
</zope:class>
|
||||||
|
|
||||||
|
<zope:subscriber
|
||||||
|
for="loops.interfaces.IConcept
|
||||||
|
zope.app.container.interfaces.IObjectRemovedEvent"
|
||||||
|
handler="loops.organize.party.removePersonReferenceFromPrincipal"
|
||||||
|
/>
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
|
|
@ -31,12 +31,14 @@ from zope.interface import implements
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
from zope.security.proxy import removeSecurityProxy
|
from zope.security.proxy import removeSecurityProxy
|
||||||
|
|
||||||
#from cybertools.organize.interfaces import IPerson
|
|
||||||
from cybertools.organize.party import Person as BasePerson
|
from cybertools.organize.party import Person as BasePerson
|
||||||
from cybertools.relation.interfaces import IRelationRegistry
|
from cybertools.typology.interfaces import IType
|
||||||
from loops.interfaces import IConcept
|
from loops.interfaces import IConcept
|
||||||
from loops.type import TypeInterfaceSourceList
|
|
||||||
from loops.organize.interfaces import IPerson
|
from loops.organize.interfaces import IPerson
|
||||||
|
from loops.type import TypeInterfaceSourceList
|
||||||
|
|
||||||
|
|
||||||
|
ANNOTATION_KEY = 'loops.organize.person'
|
||||||
|
|
||||||
|
|
||||||
# register IPerson as a type interface - (TODO: use a function for this)
|
# register IPerson as a type interface - (TODO: use a function for this)
|
||||||
|
@ -52,6 +54,7 @@ class Person(BasePerson):
|
||||||
adapts(IConcept)
|
adapts(IConcept)
|
||||||
|
|
||||||
__attributes = ('context', '__parent__', 'userId',)
|
__attributes = ('context', '__parent__', 'userId',)
|
||||||
|
__schemas = list(IPerson) + list(IConcept)
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
self.context = context # to get the permission stuff right
|
self.context = context # to get the permission stuff right
|
||||||
|
@ -69,31 +72,37 @@ class Person(BasePerson):
|
||||||
setattr(self.context, '_' + attr, value)
|
setattr(self.context, '_' + attr, value)
|
||||||
|
|
||||||
def checkAttr(self, attr):
|
def checkAttr(self, attr):
|
||||||
if attr not in list(IPerson) + list(IConcept):
|
if attr not in self.__schemas:
|
||||||
raise AttributeError(attr)
|
raise AttributeError(attr)
|
||||||
|
|
||||||
def getUserId(self):
|
def getUserId(self):
|
||||||
return getattr(self.context, '_userId', None)
|
return getattr(self.context, '_userId', None)
|
||||||
def setUserId(self, userId):
|
def setUserId(self, userId):
|
||||||
auth = self.authentication
|
auth = self.authentication
|
||||||
oldUserId = self.userId
|
|
||||||
if oldUserId and oldUserId != userId:
|
|
||||||
principal = self.getPrincipalForUserId(oldUserId)
|
|
||||||
if principal is not None:
|
|
||||||
pa = annotations(principal)
|
|
||||||
pa['loops.organize.person'] = None
|
|
||||||
if userId:
|
if userId:
|
||||||
principal = auth.getPrincipal(userId)
|
principal = auth.getPrincipal(userId)
|
||||||
pa = annotations(principal)
|
pa = annotations(principal)
|
||||||
relations = component.getUtility(IRelationRegistry)
|
person = pa.get(ANNOTATION_KEY, None)
|
||||||
uid = relations.getUniqueIdForObject(self.context)
|
if person is not None and person != self.context:
|
||||||
pa['loops.organize.person'] = uid
|
raise ValueError(
|
||||||
|
'There is alread a person (%s) assigned to user %s.'
|
||||||
|
% (zapi.getName(person), userId))
|
||||||
|
pa[ANNOTATION_KEY] = self.context
|
||||||
|
oldUserId = self.userId
|
||||||
|
if oldUserId and oldUserId != userId:
|
||||||
|
self.removeReferenceFromPrincipal(oldUserId)
|
||||||
self.context._userId = userId
|
self.context._userId = userId
|
||||||
userId = property(getUserId, setUserId)
|
userId = property(getUserId, setUserId)
|
||||||
|
|
||||||
|
def removeReferenceFromPrincipal(self, userId):
|
||||||
|
principal = self.getPrincipalForUserId(userId)
|
||||||
|
if principal is not None:
|
||||||
|
pa = annotations(principal)
|
||||||
|
pa[ANNOTATION_KEY] = None
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def authentication(self):
|
def authentication(self):
|
||||||
return component.getUtility(IAuthentication, context=self.context)
|
return getAuthenticationUtility(self.context)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def principal(self):
|
def principal(self):
|
||||||
|
@ -110,3 +119,20 @@ class Person(BasePerson):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def getAuthenticationUtility(context):
|
||||||
|
return component.getUtility(IAuthentication, context=context)
|
||||||
|
|
||||||
|
|
||||||
|
def removePersonReferenceFromPrincipal(context, event):
|
||||||
|
""" Handles IObjectRemoved event for concepts used as persons.
|
||||||
|
"""
|
||||||
|
if IConcept.providedBy(context):
|
||||||
|
# this does not work as the context is already removed from the
|
||||||
|
# relation registry:
|
||||||
|
#if IType(context).typeInterface == IPerson:
|
||||||
|
# person = IPerson(context)
|
||||||
|
# if person.userId:
|
||||||
|
if getattr(context, '_userId', None):
|
||||||
|
person = IPerson(context)
|
||||||
|
person.removeReferenceFromPrincipal(person.userId)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue