Ignore:
Timestamp:
21 May 2011, 01:31:03 (14 years ago)
Author:
uli
Message:

Add local roles dicts for user accounts. That seems to
need pretty much machinery, but seems also to work. So,
why not?

We have a new event type, that should be fired when
a local role is set or unset somewhere.

We have also two new event subscribers, one listening
to the new event (and then updates the user account
local roles listings), and another one listening to
IObjectRemoved events.

The latter is the trick to keep the local role listings
in user accounts more or less up-to-date. Without it
these lists would grow and grow, not noticing that
the objects they refer to, have gone already.

We now must think about subscribing to other events.
What happens, when an object is moved or copied.
Will the local roles then be copied as well? And would
that fact be reflected in user accounts?

Beside this we have to find all places in sources
where local roles are set/unset and trigger the new
LocalRoleSetEvent? defined in users.py.

Samples for the whole new stuff are in authentication.txt.

Location:
main/waeup.sirp/trunk/src/waeup/sirp
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.sirp/trunk/src/waeup/sirp/authentication.py

    r6156 r6180  
    5959    grok.implements(IUserAccount)
    6060
     61    _local_roles = dict()
     62
    6163    def __init__(self, name, password, title=None, description=None,
    6264                 roles = []):
     
    7072        self.setPassword(password)
    7173        self.setRoles(roles)
     74        # We don't want to share this dict with other accounts
     75        self._local_roles = dict()
    7276
    7377    def setPassword(self, password):
     
    98102
    99103    roles = property(getRoles, setRoles)
     104
     105    def getLocalRoles(self):
     106        return self._local_roles
     107
     108    def notifyLocalRoleChanged(self, obj, role_id, granted=True):
     109        objects = self._local_roles.get(role_id, [])
     110        if granted and obj not in objects:
     111            objects.append(obj)
     112        if not granted and obj in objects:
     113            objects.remove(obj)
     114        self._local_roles[role_id] = objects
     115        if len(objects) == 0:
     116            del self._local_roles[role_id]
     117        return
    100118
    101119    def _getPrincipalRoleManager(self):
  • main/waeup.sirp/trunk/src/waeup/sirp/authentication.txt

    r5404 r6180  
    1212Before we can check access we have to create an app:
    1313
     14  >>> from zope.component.hooks import setSite # only needed in tests
    1415  >>> from waeup.sirp.app import University
    1516  >>> root = getRootFolder()
    1617  >>> u = University()
    1718  >>> root['app'] = u
     19  >>> setSite(root['app'])                     # only needed in tests
    1820
    1921To make sure, we can 'watch' pages, we first have to initialize our
     
    4244See ``users.txt`` for details about the UserContainer we use here.
    4345
     46Users and local roles
     47=====================
     48
     49Accounts also hold infos about local roles assigned to a user. In the
     50beginning, users have no local roles at all:
     51
     52  >>> alice.getLocalRoles()
     53  {}
     54
     55But we can tell an account, that Alice got some role for a certain
     56object:
     57
     58  >>> chalet = object()
     59  >>> root['app']['chalet'] = chalet
     60  >>> alice.notifyLocalRoleChanged(chalet, 'BigBoss', granted=True)
     61
     62Now Alice is the Big Boss:
     63
     64  >>> alice.getLocalRoles()
     65  {'BigBoss': [<object object at 0x...>]}
     66
     67When we do not want Alice to be the Big Boss we can tell that too:
     68
     69  >>> alice.notifyLocalRoleChanged(chalet, 'BigBoss', granted=False)
     70  >>> alice.getLocalRoles()
     71  {}
     72
     73We can also use events to trigger such actions. This is recommended
     74because we do not neccessarily know where Alice lives:
     75
     76  >>> from waeup.sirp.users import LocalRoleSetEvent
     77  >>> from zope.event import notify
     78  >>> notify(LocalRoleSetEvent(chalet, 'BigBoss', 'alice',
     79  ...                          granted=True))
     80  >>> alice.getLocalRoles()
     81  {'BigBoss': [<object object at 0x...>]}
     82
     83When objects are deleted, local roles are also deleted
     84semi-magically. This happens through event subscribers listening to
     85IObjectRemovedEvents. The latters are naturally only fired when ZODB
     86stored objects are removed. Furthermore this subscriber reads the
     87internal local roles table.
     88
     89We create a faculty and grant Bob a local role:
     90
     91   >>> from zope.securitypolicy.interfaces import IPrincipalRoleManager
     92   >>> from waeup.sirp.university.faculty import Faculty
     93   >>> faculty = Faculty()
     94   >>> root['app']['bobs_fac'] = faculty
     95   >>> role_manager = IPrincipalRoleManager(faculty)
     96   >>> role_manager.assignRoleToPrincipal(
     97   ...    'waeup.PortalManager', 'bob')
     98
     99We notify the machinery about that fact:
     100
     101   >>> notify(LocalRoleSetEvent(faculty, 'waeup.PortalManager', 'bob',
     102   ...                          granted=True))
     103   >>> bob = root['app']['users']['bob']
     104   >>> bob.getLocalRoles()
     105   {'waeup.PortalManager': [<waeup.sirp...Faculty object at 0x...>]}
     106
     107When we delete the faculty from ZODB, also Bobs roles are modified:
     108
     109   >>> del root['app']['bobs_fac']
     110   >>> bob.getLocalRoles()
     111   {}
    44112
    45113Logging in via side bar
  • main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py

    r6174 r6180  
    266266    """
    267267
     268class ILocalRoleSetEvent(IObjectEvent):
     269    """A local role was granted/revoked for a principal on an object.
     270    """
     271    role_id = Attribute(
     272        "The role id that was set.")
     273    principal_id = Attribute(
     274        "The principal id for which the role was granted/revoked.")
     275    granted = Attribute(
     276        "Boolean. If false, then the role was revoked.")
     277
    268278class IQueryResultItem(Interface):
    269279    """An item in a search result.
  • main/waeup.sirp/trunk/src/waeup/sirp/users.py

    r4920 r6180  
    22"""
    33import grok
     4from zope.event import notify
     5from zope.interface import Interface
     6from zope.securitypolicy.interfaces import IPrincipalRoleMap
    47from waeup.sirp.authentication import Account
    5 from waeup.sirp.interfaces import IUserContainer
     8from waeup.sirp.interfaces import IUserContainer, ILocalRoleSetEvent
    69
    710class UserContainer(grok.Container):
     
    2629        """
    2730        self[account.name] = account
    28        
     31
    2932    def delUser(self, name):
    3033        """Delete user, if an account with the given name exists.
     
    3437        if name in self.keys():
    3538            del self[name]
     39
     40class LocalRoleSetEvent(object):
     41
     42    grok.implements(ILocalRoleSetEvent)
     43
     44    def __init__(self, object, role_id, principal_id, granted=True):
     45        self.object = object
     46        self.role_id = role_id
     47        self.principal_id = principal_id
     48        self.granted = granted
     49
     50@grok.subscribe(Interface, ILocalRoleSetEvent)
     51def handle_local_role_changed(obj, event):
     52    site = grok.getSite()
     53    if site is None:
     54        return
     55    users = site['users']
     56    role_id = event.role_id
     57    if event.principal_id not in users.keys():
     58        return
     59    user = users[event.principal_id]
     60    user.notifyLocalRoleChanged(event.object, event.role_id, event.granted)
     61    return
     62
     63@grok.subscribe(Interface, grok.IObjectRemovedEvent)
     64def handle_local_roles_on_obj_removal(obj, event):
     65    role_map = IPrincipalRoleMap(obj)
     66    for local_role, user_name, setting in role_map.getPrincipalsAndRoles():
     67        notify(LocalRoleSetEvent(
     68                obj, local_role, user_name, granted=False))
     69    return
Note: See TracChangeset for help on using the changeset viewer.