22Security Mechanisms
33===================
44
5- :Version: $Revision: 1.1 $
5+ :Version: $Revision: 1.2 $
66
77Current situation
88=================
6767 - harder to determine the relationship between user interaction and hyperdb
6868 permission.
6969 - a lot of work to define
70+ - must special-case to handle by-node permissions (editing user details,
71+ having private messages)
72+
7073
7174User-interface control
7275----------------------
@@ -92,9 +95,17 @@ Logical control
9295---------------
9396
9497At each point that requires an action to be performed, the security mechanisms
95- are asked if the current user has permission. There is no possibility to have
98+ are asked if the current user has permission. Since code must call the
99+ check function to raise a denial, there is no possibility to have automatic
96100default of deny in this situation.
97101
102+ In practice, this is implemented as:
103+
104+ 1. there's a mapping of user -> role (in hyperdb)
105+ 2. there's a mapping of role -> permission (in code)
106+ 3. there's a function that's available to all roundup code that can ask
107+ whether a particular user has a particular permission.
108+
98109Pros:
99110
100111 - quite obvious what is going on
@@ -106,7 +117,6 @@ Cons:
106117 mirroring actual user interface controls.
107118
108119
109-
110120Applying controls to users
111121==========================
112122
@@ -117,6 +127,82 @@ allow the multiple assignment of Roles to Users, and multiple Permissions to
117127Roles. These definitions will be stored in the hyperdb.
118128
119129
130+ A permission module defines::
131+
132+ class InMemoryImmutableClass(hyperdb.Class):
133+ ''' Don't allow changes to this class's nodes.
134+ '''
135+ def __init__(self, db, classname, **properties):
136+ ''' Set up an in-memory store for the nodes of this class
137+ '''
138+
139+ def create(self, **propvalues):
140+ ''' Create a new node in the in-memory store
141+ '''
142+
143+ def get(self, nodeid, propname, default=_marker, cache=1):
144+ ''' Get the node from the in-memory store
145+ '''
146+
147+ def set(self, *args):
148+ raise ValueError, "%s are immutable"%self.__class__.__name__
149+
150+ class PermissionClass(InMemoryImmutableClass):
151+ ''' Include the default attributes:
152+ - name (String, key)
153+ - description (String)
154+ '''
155+
156+ class RoleClass(InMemoryImmutableClass):
157+ ''' Include the default attributes:
158+ - name (String, key)
159+ - description (String)
160+ - permissions (PermissionClass Multilink)
161+ '''
162+
163+ def hasPermission(db, userid, permission):
164+ ''' Look through all the Roles, and hence Permissions, and see if
165+ "permission" is there
166+ '''
167+
168+
169+ The instance dbinit module then has::
170+
171+ in open():
172+
173+ perm = permission.PermissionClass(db, "permission")
174+ role = permission.RoleClass(db, "role")
175+
176+ wa = perm.create(name="Web Access",
177+ description="User may log in through the web")
178+ wr = perm.create(name="Web Registration",
179+ description="User may register through the web")
180+ ma = perm.create(name="Mail Access",
181+ description="User may log in through email")
182+ mr = perm.create(name="Mail Registration",
183+ description="User may register through email")
184+ aa = perm.create(name="Access Everything",
185+ description="User may access everthing")
186+ role.create(name="User", description="A regular user, no privs",
187+ permissions=[wa, wr, ma, mr])
188+ role.create(name="Admin", description="An admin user, full privs",
189+ permissions=[aa])
190+ ro = role.create(name="No Rego", description="A user who can't register",
191+ permissions=[wa, ma])
192+
193+ in init():
194+
195+ r = db.getclass('role').find('Admin')
196+ user.create(username="admin", password=Password(adminpw),
197+ address=instance_config.ADMIN_EMAIL, roles=[r])
198+
199+ # choose your anonymous user access permission here
200+ #r = db.getclass('role').find('No Rego')
201+ r = db.getclass('role').find('User')
202+ user.create(username="anonymous", roles=[r])
203+
204+
205+
120206Use cases
121207=========
122208
@@ -133,48 +219,3 @@ system
133219privacy
134220 issues that are only visible to some users
135221
136-
137- Discussion
138- ==========
139-
140- Date: Thu, 2 May 2002 11:46:56 -0400
141- 142- 143- I've really appreciated roundup so far. It has been very easy to create my own
144- template that adds functionality for my specific purpose. One area, for my
145- needs, that does not seem to be currently addressed in roundup is roles of
146- users. I have various roles that the users of my instance of roundup can have.
147- I have:
148-
149- 1) end users that can submit bugs, request new features, request support.
150- 2) developers that can fix bugs, implement new features provide support
151- 3) approvers/managers that can approve new features and signoff bug fixes
152- 4) administrators that can add users and set users roles
153- 5) processors - this is isn't totally thought out yet, but for me it would be an
154- automated request handler that would run various production scripts.
155-
156- Each of these roles need to have specific functionality within the web client
157- (and possibly the email client -- but I haven't looked at that much yet). An
158- example is that I don't want end users to be able to assign a specific developer
159- to a problem or support issue. I think that some of my functionality can be
160- implemented via the detectors, but I haven't fully researched it yet.
161-
162- So far, I have added a new class to the database called role which contains the
163- various roles outlined above. I have added a multilink in the user class to the
164- new role class. I have modified the base code in the cgi client to use the new
165- admin role when checking for admin instead of using the user id. I am working
166- on implementing the role for access to the individual forms and even specific
167- fields on the forms. Has anyone else done this or seen a need to do this?
168-
169- I am planning on implementing this as an optional feature - basically the
170- security will be handled in a separate module so that a site could implement the
171- role functionality or exclude it by using the module that fits their needs. My
172- current changes to the admin checks would be pulled out into a separate
173- replaceable module. So if an implementation did not want to use roles, the
174- check would just check the user id to see if it was equal to "admin". In my
175- case, it would check the role of the user to see if it contained the admin role.
176-
177- If anyone else is interested in this, I will send the patches in when I am
178- completed with this. If anyone else has worked on this (and hopefully gotten
179- farther than I), please let me know.
180-
0 commit comments