Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/securitypolicy.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/securitypolicy.py	(revision 7125)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/securitypolicy.py	(revision 7126)
@@ -32,5 +32,4 @@
 from zope.securitypolicy.principalpermission import (
     AnnotationPrincipalPermissionManager,)
-from zope.securitypolicy.securitymap import AnnotationSecurityMap
 from zope.securitypolicy.settings import Allow, Deny, Unset
 from waeup.sirp.applicants.interfaces import IApplicant
@@ -39,10 +38,16 @@
 grok.context(IApplicant)
 
-class ApplicantSecurityMap(AnnotationSecurityMap):
-    pass
-
 class ApplicantPrincipalRoleManager(AnnotationPrincipalRoleManager,
                                     grok.Adapter):
     grok.provides(IPrincipalRoleManager)
+
+    #: The attribute name to lookup for additional roles
+    extra_attrib = 'course1'
+
+    #: List of role names to look for in `extra_attrib` and parents.
+    external_rolenames = ['waeup.local.ClearanceOfficer',]
+
+    #: Role to add in case one of the above roles was found.
+    additional_rolename = 'waeup.ApplicationsOfficer'
 
     def getRolesForPrincipal(self, principal_id):
@@ -53,8 +58,12 @@
         to the context applicant.
 
-        If the given principal has 'waeup.local.ClearanceOfficer'
-        permissions set on the connected department, it additionally
-        gets 'waeup.ApplicationsOfficer' role for the context
+        If the given principal has at least one of the
+        `external_rolenames` roles granted for the external object, it
+        additionally gets `additional_rolename` role for the context
         applicant.
+
+        For the additional roles the `extra_attrib` and all its parent
+        objects are looked up, because 'role inheritance' does not
+        work on that basic level of permission handling.
 
         Some advantages of this approach:
@@ -71,4 +80,9 @@
         - More expensive role lookups when a clearance officer wants
           to see an applicant form.
+
+        This implementation is designed to be usable also for other
+        contexts than applicants. You can inherit from it and set
+        different role names to lookup/set easily via the static class
+        attributes.
         """
         result = super(ApplicantPrincipalRoleManager, self
@@ -79,20 +93,20 @@
             return result
         # The principal has no local roles yet. Let's lookup the
-        # connected dept.
-        course = getattr(self._context, 'course1', None)
-        dept = getattr(
-            getattr(course, '__parent__', None),
-            '__parent__', None)
-        if dept is None:
-            # No deptartment, no extra roles.
-            return result
-        dept_roles = IPrincipalRoleManager(dept).getRolesForPrincipal(
-            principal_id)
-        # 'Grant' 'waeup.ApplicationsOfficer' permissions (allow, deny
-        # or unset) for the passed in principal id if it has clearance
-        # officer role on the connected department.
-        for role_id, setting in dept_roles:
-            if role_id == 'waeup.local.ClearanceOfficer':
-                result.append(
-                    ('waeup.ApplicationsOfficer', setting))
+        # connected course, dept, etc.
+        obj = getattr(self._context, self.extra_attrib, None)
+        # lookup local roles for connected course and all parent
+        # objects. This way we fake 'role inheritance'.
+        while obj is not None:
+            extra_roles = IPrincipalRoleManager(obj).getRolesForPrincipal(
+                principal_id)
+            for role_id, setting in extra_roles:
+                if role_id in self.external_rolenames:
+                    # Found role in external attribute or parent
+                    # thereof. 'Grant' additional role
+                    # permissions (allow, deny or unset) for the
+                    # passed in principal id.
+                    result.append(
+                        (self.additional_rolename, setting))
+                    return result
+            obj = getattr(obj, '__parent__', None)
         return result
