7475ca62eb9067272f1088094522ee4cee47a452
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)