Code

Fix last commit to make editing/creating items work again.
[roundup.git] / roundup / security.py
1 """Handle the security declarations used in Roundup trackers.
2 """
3 __docformat__ = 'restructuredtext'
5 import weakref
7 from roundup import hyperdb
9 class Permission:
10     ''' Defines a Permission with the attributes
11         - name
12         - description
13         - klass (optional)
15         The klass may be unset, indicating that this permission is not
16         locked to a particular class. That means there may be multiple
17         Permissions for the same name for different classes.
18     '''
19     def __init__(self, name='', description='', klass=None):
20         self.name = name
21         self.description = description
22         self.klass = klass
24     def __repr__(self):
25         return '<Permission 0x%x %r,%r>'%(id(self), self.name, self.klass)
27 class Role:
28     ''' Defines a Role with the attributes
29         - name
30         - description
31         - permissions
32     '''
33     def __init__(self, name='', description='', permissions=None):
34         self.name = name.lower()
35         self.description = description
36         if permissions is None:
37             permissions = []
38         self.permissions = permissions
40     def __repr__(self):
41         return '<Role 0x%x %r,%r>'%(id(self), self.name, self.permissions)
43 class Security:
44     def __init__(self, db):
45         ''' Initialise the permission and role classes, and add in the
46             base roles (for admin user).
47         '''
48         self.db = weakref.proxy(db)       # use a weak ref to avoid circularity
50         # permssions are mapped by name to a list of Permissions by class
51         self.permission = {}
53         # roles are mapped by name to the Role
54         self.role = {}
56         # the default Roles
57         self.addRole(name="User", description="A regular user, no privs")
58         self.addRole(name="Admin", description="An admin user, full privs")
59         self.addRole(name="Anonymous", description="An anonymous user")
61         ee = self.addPermission(name="Edit",
62             description="User may edit everthing")
63         self.addPermissionToRole('Admin', ee)
64         ae = self.addPermission(name="View",
65             description="User may access everything")
66         self.addPermissionToRole('Admin', ae)
67         reg = self.addPermission(name="Register Web",
68             description="User may register through the web")
69         reg = self.addPermission(name="Register Email",
70             description="User may register through the email")
72         # initialise the permissions and roles needed for the UIs
73         from roundup.cgi import client
74         client.initialiseSecurity(self)
75         from roundup import mailgw
76         mailgw.initialiseSecurity(self)
78     def getPermission(self, permission, classname=None):
79         ''' Find the Permission matching the name and for the class, if the
80             classname is specified.
82             Raise ValueError if there is no exact match.
83         '''
84         if not self.permission.has_key(permission):
85             raise ValueError, 'No permission "%s" defined'%permission
87         # look through all the permissions of the given name
88         for perm in self.permission[permission]:
89             # if we're passed a classname, the permission must match
90             if perm.klass is not None and perm.klass == classname:
91                 return perm
92             # otherwise the permission klass must be unset
93             elif not perm.klass and not classname:
94                 return perm
95         raise ValueError, 'No permission "%s" defined for "%s"'%(permission,
96             classname)
98     def hasPermission(self, permission, userid, classname=None):
99         ''' Look through all the Roles, and hence Permissions, and see if
100             "permission" is there for the specified classname.
101         '''
102         roles = self.db.user.get(userid, 'roles')
103         if roles is None:
104             return 0
105         for rolename in [x.lower().strip() for x in roles.split(',')]:
106             if not rolename or not self.role.has_key(rolename):
107                 continue
108             # for each of the user's Roles, check the permissions
109             for perm in self.role[rolename].permissions:
110                 # permission name match?
111                 if perm.name == permission:
112                     # permission klass match?
113                     if perm.klass is None or perm.klass == classname:
114                         # we have a winner
115                         return 1
116         return 0
118     def hasNodePermission(self, classname, nodeid, **propspec):
119         ''' Check the named properties of the given node to see if the
120             userid appears in them. If it does, then the user is granted
121             this permission check.
123             'propspec' consists of a set of properties and values that
124             must be present on the given node for access to be granted.
126             If a property is a Link, the value must match the property
127             value. If a property is a Multilink, the value must appear
128             in the Multilink list.
129         '''
130         klass = self.db.getclass(classname)
131         properties = klass.getprops()
132         for k,v in propspec.items():
133             value = klass.get(nodeid, k)
134             if isinstance(properties[k], hyperdb.Multilink):
135                 if v not in value:
136                     return 0
137             else:
138                 if v != value:
139                     return 0
140         return 1
142     def addPermission(self, **propspec):
143         ''' Create a new Permission with the properties defined in
144             'propspec'
145         '''
146         perm = Permission(**propspec)
147         self.permission.setdefault(perm.name, []).append(perm)
148         return perm
150     def addRole(self, **propspec):
151         ''' Create a new Role with the properties defined in 'propspec'
152         '''
153         role = Role(**propspec)
154         self.role[role.name] = role
155         return role
157     def addPermissionToRole(self, rolename, permission):
158         ''' Add the permission to the role's permission list.
160             'rolename' is the name of the role to add the permission to.
161         '''
162         role = self.role[rolename.lower()]
163         role.permissions.append(permission)
165 # vim: set filetype=python ts=4 sw=4 et si