Code

7475ca62eb9067272f1088094522ee4cee47a452
[roundup.git] / roundup / security.py
1 import weakref
3 from roundup import hyperdb, volatiledb
5 class PermissionClass(volatiledb.VolatileClass):
6     ''' Include the default attributes:
7         - name (String)
8         - classname (String)
9         - description (String)
11         The classname 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, db, classname, **properties):
16         """ set up the default properties
17         """
18         if not properties.has_key('name'):
19             properties['name'] = hyperdb.String()
20         if not properties.has_key('klass'):
21             properties['klass'] = hyperdb.String()
22         if not properties.has_key('description'):
23             properties['description'] = hyperdb.String()
24         volatiledb.VolatileClass.__init__(self, db, classname, **properties)
26 class RoleClass(volatiledb.VolatileClass):
27     ''' Include the default attributes:
28         - name (String, key)
29         - description (String)
30         - permissions (PermissionClass Multilink)
31     '''
32     def __init__(self, db, classname, **properties):
33         """ set up the default properties
34         """
35         if not properties.has_key('name'):
36             properties['name'] = hyperdb.String()
37         if not properties.has_key('description'):
38             properties['description'] = hyperdb.String()
39         if not properties.has_key('permissions'):
40             properties['permissions'] = hyperdb.Multilink('permission')
41         volatiledb.VolatileClass.__init__(self, db, classname, **properties)
42         self.setkey('name')
44 class Security:
45     def __init__(self, db):
46         ''' Initialise the permission and role classes, and add in the
47             base roles (for admin user).
48         '''
49         # use a weak ref to avoid circularity
50         self.db = weakref.proxy(db)
52         # create the permission class instance (we only need one))
53         self.permission = PermissionClass(db, "permission")
55         # create the role class instance (we only need one)
56         self.role = RoleClass(db, "role")
58         # the default Roles
59         self.addRole(name="User", description="A regular user, no privs")
60         self.addRole(name="Admin", description="An admin user, full privs")
61         self.addRole(name="Anonymous", description="An anonymous user")
63         ee = self.addPermission(name="Edit",
64             description="User may edit everthing")
65         self.addPermissionToRole('Admin', ee)
66         ae = self.addPermission(name="Access",
67             description="User may access everything")
68         self.addPermissionToRole('Admin', ae)
69         ae = self.addPermission(name="Assign",
70             description="User may be assigned to anything")
71         self.addPermissionToRole('Admin', ae)
72         reg = self.addPermission(name="Register Web",
73             description="User may register through the web")
74         self.addPermissionToRole('Anonymous', reg)
75         reg = self.addPermission(name="Register Email",
76             description="User may register through the email")
77         self.addPermissionToRole('Anonymous', reg)
79         # initialise the permissions and roles needed for the UIs
80         from roundup import cgi_client, mailgw
81         cgi_client.initialiseSecurity(self)
82         mailgw.initialiseSecurity(self)
84     def hasClassPermission(self, classname, permission, userid):
85         ''' Look through all the Roles, and hence Permissions, and see if
86             "permission" is there for the specified classname.
88         '''
89         roles = self.db.user.get(userid, 'roles')
90         for roleid in roles:
91             for permissionid in self.db.role.get(roleid, 'permissions'):
92                 if self.db.permission.get(permissionid, 'name') != permission:
93                     continue
94                 klass = self.db.permission.get(permissionid, 'klass')
95                 if klass is None or klass == classname:
96                     return 1
97         return 0
99     def hasNodePermission(self, classname, nodeid, **propspec):
100         ''' Check the named properties of the given node to see if the
101             userid appears in them. If it does, then the user is granted
102             this permission check.
104             'propspec' consists of a set of properties and values that
105             must be present on the given node for access to be granted.
107             If a property is a Link, the value must match the property
108             value. If a property is a Multilink, the value must appear
109             in the Multilink list.
110         '''
111         klass = self.db.getclass(classname)
112         properties = klass.getprops()
113         for k,v in propspec.items():
114             value = klass.get(nodeid, k)
115             if isinstance(properties[k], hyperdb.Multilink):
116                 if v not in value:
117                     return 0
118             else:
119                 if v != value:
120                     return 0
121         return 1
123     def addPermission(self, **propspec):
124         ''' Create a new Permission with the properties defined in
125             'propspec'
126         '''
127         return self.db.permission.create(**propspec)
129     def addRole(self, **propspec):
130         ''' Create a new Role with the properties defined in 'propspec'
131         '''
132         return self.db.role.create(**propspec)
134     def addPermissionToRole(self, rolename, permissionid):
135         ''' Add the permission to the role's permission list.
137             'rolename' is the name of the role to add 'permissionid'.
138         '''
139         roleid = self.db.role.lookup(rolename)
140         permissions = self.db.role.get(roleid, 'permissions')
141         permissions.append(permissionid)
142         self.db.role.set(roleid, permissions=permissions)