Code

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