source: main/waeup.sirp/trunk/src/waeup/sirp/students/dynamicroles.py @ 7206

Last change on this file since 7206 was 7159, checked in by Henrik Bettermann, 13 years ago

Rename securitypolicy module to dynamicroles.

  • Property svn:keywords set to Id
File size: 4.7 KB
Line 
1## $Id: dynamicroles.py 7159 2011-11-21 10:11:07Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Security policy components for students.
19
20Students need special security policy treatment, as officers with
21local roles for departments and faculties might have additional
22permissions (local roles on depts/faculties) here.
23"""
24import grok
25from zope.securitypolicy.interfaces import (
26    IPrincipalRoleManager, IPrincipalPermissionManager,)
27from zope.securitypolicy.principalrole import AnnotationPrincipalRoleManager
28from zope.securitypolicy.principalpermission import (
29    AnnotationPrincipalPermissionManager,)
30from zope.securitypolicy.settings import Allow, Deny, Unset
31from waeup.sirp.students.interfaces import IStudent
32
33# All components in here have the same context: Student instances
34grok.context(IStudent)
35
36class StudentPrincipalRoleManager(AnnotationPrincipalRoleManager,
37                                    grok.Adapter):
38    grok.provides(IPrincipalRoleManager)
39
40    #: The attribute name to lookup for additional roles
41    extra_attrib = 'certificate'
42    subcontainer = 'studycourse'
43
44    #: List of role names to look for in `extra_attrib` and parents.
45    external_rolenames = ['waeup.local.ClearanceOfficer',]
46
47    #: Role to add in case one of the above roles was found.
48    additional_rolename = 'waeup.StudentsClearanceOfficer'
49
50    def getRolesForPrincipal(self, principal_id):
51        """Get roles for principal with id `principal_id`.
52
53        Different to the default implementation, this method also
54        takes into account local roles set on any department connected
55        to the context student.
56
57        If the given principal has at least one of the
58        `external_rolenames` roles granted for the external object, it
59        additionally gets `additional_rolename` role for the context
60        student.
61
62        For the additional roles the `extra_attrib` and all its parent
63        objects are looked up, because 'role inheritance' does not
64        work on that basic level of permission handling.
65
66        Some advantages of this approach:
67
68        - we don't have to store extra local roles for clearance
69          officers in ZODB for each student
70
71        - when local roles on a department change, we don't have to
72          update thousands of students; the local role is assigned
73          dynamically.
74
75        Disadvantage:
76
77        - More expensive role lookups when a clearance officer wants
78          to see an student form.
79
80        This implementation is designed to be usable also for other
81        contexts than students. You can inherit from it and set
82        different role names to lookup/set easily via the static class
83        attributes.
84        """
85        apr_manager = AnnotationPrincipalRoleManager(self._context)
86        result = apr_manager.getRolesForPrincipal(principal_id)
87        if result != []:
88            # If there are local roles defined here, no additional
89            # lookup is done.
90            return result
91        # The principal has no local roles yet. Let's lookup the
92        # connected course, dept, etc.
93        if self.subcontainer:
94            obj = getattr(
95                self._context[self.subcontainer], self.extra_attrib, None)
96        else:
97            obj = getattr(self._context, self.extra_attrib, None)
98        # lookup local roles for connected course and all parent
99        # objects. This way we fake 'role inheritance'.
100        while obj is not None:
101            extra_roles = IPrincipalRoleManager(obj).getRolesForPrincipal(
102                principal_id)
103            for role_id, setting in extra_roles:
104                if role_id in self.external_rolenames:
105                    # Found role in external attribute or parent
106                    # thereof. 'Grant' additional role
107                    # permissions (allow, deny or unset) for the
108                    # passed in principal id.
109                    result.append(
110                        (self.additional_rolename, setting))
111                    return result
112            obj = getattr(obj, '__parent__', None)
113        return result
Note: See TracBrowser for help on using the repository browser.