Ignore:
Timestamp:
10 Sep 2012, 11:05:07 (12 years ago)
Author:
uli
Message:

Merge changes from trunk, r8786-HEAD

Location:
main/waeup.kofa/branches/uli-async-update
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/branches/uli-async-update

  • main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/applicants/dynamicroles.py

    r7811 r9169  
    2424import grok
    2525from zope.securitypolicy.interfaces import IPrincipalRoleManager
     26from zope.securitypolicy.principalrole import AnnotationPrincipalRoleManager
    2627from waeup.kofa.applicants.interfaces import IApplicant
    27 from waeup.kofa.students.dynamicroles import StudentPrincipalRoleManager
    2828
    2929# All components in here have the same context: Applicant instances
    3030grok.context(IApplicant)
    3131
    32 class ApplicantPrincipalRoleManager(StudentPrincipalRoleManager):
    33 
     32class ApplicantPrincipalRoleManager(AnnotationPrincipalRoleManager,
     33                                    grok.Adapter):
    3434    grok.provides(IPrincipalRoleManager)
    3535
    3636    #: The attribute name to lookup for additional roles
    3737    extra_attrib = 'course1'
    38     subcontainer = None
    3938
    4039    # Role name mapping:
     
    4544        'waeup.local.ClearanceOfficer':'waeup.ApplicationsOfficer',
    4645        }
     46
     47    def getRolesForPrincipal(self, principal_id):
     48        """Get roles for principal with id `principal_id`.
     49
     50        Different to the default implementation, this method also
     51        takes into account local roles set on any department connected
     52        to the context student.
     53
     54        If the given principal has at least one of the
     55        `external_rolenames` roles granted for the external object, it
     56        additionally gets `additional_rolename` role for the context
     57        student.
     58
     59        For the additional roles the `extra_attrib` and all its parent
     60        objects are looked up, because 'role inheritance' does not
     61        work on that basic level of permission handling.
     62
     63        Some advantages of this approach:
     64
     65        - we don't have to store extra local roles for clearance
     66          officers in ZODB for each student
     67
     68        - when local roles on a department change, we don't have to
     69          update thousands of students; the local role is assigned
     70          dynamically.
     71
     72        Disadvantage:
     73
     74        - More expensive role lookups when a clearance officer wants
     75          to see an student form.
     76
     77        This implementation is designed to be usable also for other
     78        contexts than students. You can inherit from it and set
     79        different role names to lookup/set easily via the static class
     80        attributes.
     81        """
     82        apr_manager = AnnotationPrincipalRoleManager(self._context)
     83        result = apr_manager.getRolesForPrincipal(principal_id)
     84        if result != []:
     85            # If there are local roles defined here, no additional
     86            # lookup is done.
     87            return result
     88        # The principal has no local roles yet. Let's lookup the
     89        # connected course, dept, etc.
     90        obj = getattr(self._context, self.extra_attrib, None)
     91        # Lookup local roles for connected course and all parent
     92        # objects. This way we fake 'role inheritance'.
     93        while obj is not None:
     94            extra_roles = IPrincipalRoleManager(obj).getRolesForPrincipal(
     95                principal_id)
     96            for role_id, setting in extra_roles:
     97                if role_id in self.rolename_mapping.keys():
     98                    # Grant additional role
     99                    # permissions (allow, deny or unset)
     100                    # according to the rolename mapping above.
     101                    result.append(
     102                        (self.rolename_mapping[role_id], setting))
     103                    return result
     104            obj = getattr(obj, '__parent__', None)
     105        return result
Note: See TracChangeset for help on using the changeset viewer.