Mercurial > p > roundup > code
comparison doc/security.txt @ 907:38a74d1351c5
documentation updates
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Mon, 29 Jul 2002 00:54:41 +0000 |
| parents | 502a5ae11cc5 |
| children | 299f4890427d |
comparison
equal
deleted
inserted
replaced
| 906:9a6a193fb62a | 907:38a74d1351c5 |
|---|---|
| 1 =================== | 1 =================== |
| 2 Security Mechanisms | 2 Security Mechanisms |
| 3 =================== | 3 =================== |
| 4 | 4 |
| 5 :Version: $Revision: 1.13 $ | 5 :Version: $Revision: 1.14 $ |
| 6 | 6 |
| 7 Current situation | 7 Current situation |
| 8 ================= | 8 ================= |
| 9 | 9 |
| 10 Current logical controls: | 10 Current logical controls: |
| 41 than the From address. Support for strong identification through digital | 41 than the From address. Support for strong identification through digital |
| 42 signatures should be added. | 42 signatures should be added. |
| 43 5. The command-line tool has no logical controls. | 43 5. The command-line tool has no logical controls. |
| 44 6. The anonymous control needs revising - there should only be one way to be | 44 6. The anonymous control needs revising - there should only be one way to be |
| 45 an anonymous user, not two (currently there is user==None and | 45 an anonymous user, not two (currently there is user==None and |
| 46 user=='anonymous). | 46 user=='anonymous'). |
| 47 | 47 |
| 48 | 48 |
| 49 Possible approaches | 49 Possible approaches |
| 50 =================== | 50 =================== |
| 51 | 51 |
| 129 | 129 |
| 130 Individual assignment of Permission to User is unwieldy. The concept of a | 130 Individual assignment of Permission to User is unwieldy. The concept of a |
| 131 Role, which encompasses several Permissions and may be assigned to many Users, | 131 Role, which encompasses several Permissions and may be assigned to many Users, |
| 132 is quite well developed in many projects. Roundup will take this path, and | 132 is quite well developed in many projects. Roundup will take this path, and |
| 133 allow the multiple assignment of Roles to Users, and multiple Permissions to | 133 allow the multiple assignment of Roles to Users, and multiple Permissions to |
| 134 Roles. These definitions will be stored in the hyperdb. They don't need to be | 134 Roles. These definitions are not persistent - they're defined when the |
| 135 pushed to the actual database though. | 135 application initialises. |
| 136 | 136 |
| 137 There will be two levels of Permission. The Class level permissions define | 137 There will be two levels of Permission. The Class level permissions define |
| 138 logical permissions associated with all nodes of a particular class (or all | 138 logical permissions associated with all nodes of a particular class (or all |
| 139 classes). The Node level permissions define logical permissions associated | 139 classes). The Node level permissions define logical permissions associated |
| 140 with specific nodes by way of their user-linked properties. | 140 with specific nodes by way of their user-linked properties. |
| 141 | 141 |
| 142 A security module defines:: | 142 The security module defines:: |
| 143 | 143 |
| 144 class InMemoryClass(hyperdb.Class): | 144 class Permission: |
| 145 ''' Just be an in-memory class | 145 ''' Defines a Permission with the attributes |
| 146 ''' | 146 - name |
| 147 def __init__(self, db, classname, **properties): | 147 - description |
| 148 ''' Set up an in-memory store for the nodes of this class | 148 - klass (optional) |
| 149 ''' | |
| 150 | |
| 151 def create(self, **propvalues): | |
| 152 ''' Create a new node in the in-memory store | |
| 153 ''' | |
| 154 | |
| 155 def get(self, nodeid, propname, default=_marker, cache=1): | |
| 156 ''' Get the node from the in-memory store | |
| 157 ''' | |
| 158 | |
| 159 def set(self, *args): | |
| 160 ''' Set values on the node | |
| 161 ''' | |
| 162 | |
| 163 class PermissionClass(InMemoryClass): | |
| 164 ''' Include the default attributes: | |
| 165 - name (String) | |
| 166 - klass (String) | |
| 167 - description (String) | |
| 168 | 149 |
| 169 The klass may be unset, indicating that this permission is not | 150 The klass may be unset, indicating that this permission is not |
| 170 locked to a particular class. That means there may be multiple | 151 locked to a particular hyperdb class. There may be multiple |
| 171 Permissions for the same name for different classes. | 152 Permissions for the same name for different classes. |
| 172 ''' | 153 ''' |
| 173 | 154 |
| 174 class RoleClass(InMemoryClass): | 155 class Role: |
| 175 ''' Include the default attributes: | 156 ''' Defines a Role with the attributes |
| 176 - name (String, key) | 157 - name |
| 177 - description (String) | 158 - description |
| 178 - permissions (PermissionClass Multilink) | 159 - permissions |
| 179 ''' | 160 ''' |
| 180 | 161 |
| 181 class Security: | 162 class Security: |
| 182 def __init__(self, db): | 163 def __init__(self, db): |
| 183 ''' Initialise the permission and role classes, and add in the | 164 ''' Initialise the permission and role stores, and add in the |
| 184 base roles (for admin user). | 165 base roles (for admin user). |
| 185 ''' | 166 ''' |
| 186 | 167 |
| 187 def hasPermission(self, db, classname, permission, userid): | 168 def getPermission(self, permission, classname=None): |
| 169 ''' Find the Permission matching the name and for the class, if the | |
| 170 classname is specified. | |
| 171 | |
| 172 Raise ValueError if there is no exact match. | |
| 173 ''' | |
| 174 | |
| 175 def hasPermission(self, permission, userid, classname=None): | |
| 188 ''' Look through all the Roles, and hence Permissions, and see if | 176 ''' Look through all the Roles, and hence Permissions, and see if |
| 189 "permission" is there for the specified classname. | 177 "permission" is there for the specified classname. |
| 190 | 178 ''' |
| 191 ''' | 179 |
| 192 | 180 def hasNodePermission(self, classname, nodeid, **propspec): |
| 193 def hasNodePermission(self, db, classname, nodeid, **propspec): | |
| 194 ''' Check the named properties of the given node to see if the | 181 ''' Check the named properties of the given node to see if the |
| 195 userid appears in them. If it does, then the user is granted | 182 userid appears in them. If it does, then the user is granted |
| 196 this permission check. | 183 this permission check. |
| 197 | 184 |
| 198 'propspec' consists of a set of properties and values that | 185 'propspec' consists of a set of properties and values that |
| 210 | 197 |
| 211 def addRole(self, **propspec): | 198 def addRole(self, **propspec): |
| 212 ''' Create a new Role with the properties defined in 'propspec' | 199 ''' Create a new Role with the properties defined in 'propspec' |
| 213 ''' | 200 ''' |
| 214 | 201 |
| 215 def addPermissionToRole(self, rolename, permissionid): | 202 def addPermissionToRole(self, rolename, permission): |
| 216 ''' Add the permission to the role's permission list. | 203 ''' Add the permission to the role's permission list. |
| 217 | 204 |
| 218 'rolename' is the name of the role to add 'permissionid'. | 205 'rolename' is the name of the role to add permission to. |
| 219 ''' | 206 ''' |
| 220 | 207 |
| 221 Modules such as ``cgi_client.py`` and ``mailgw.py`` define their own | 208 Modules such as ``cgi_client.py`` and ``mailgw.py`` define their own |
| 222 permissions like so (this example is ``cgi_client.py``):: | 209 permissions like so (this example is ``cgi_client.py``):: |
| 223 | 210 |
| 246 db.security.addPermissionToRole('User', ai) | 233 db.security.addPermissionToRole('User', ai) |
| 247 | 234 |
| 248 In the dbinit ``init()``:: | 235 In the dbinit ``init()``:: |
| 249 | 236 |
| 250 # create the two default users | 237 # create the two default users |
| 251 r = db.getclass('role').lookup('Admin') | |
| 252 user.create(username="admin", password=Password(adminpw), | 238 user.create(username="admin", password=Password(adminpw), |
| 253 address=instance_config.ADMIN_EMAIL, roles='Admin') | 239 address=instance_config.ADMIN_EMAIL, roles='Admin') |
| 254 r = db.getclass('role').lookup('Anonymous') | |
| 255 user.create(username="anonymous", roles='Anonymous') | 240 user.create(username="anonymous", roles='Anonymous') |
| 256 | 241 |
| 257 Then in the code that matters, calls to ``hasPermission`` and | 242 Then in the code that matters, calls to ``hasPermission`` and |
| 258 ``hasNodePermission`` are made to determine if the user has permission | 243 ``hasNodePermission`` are made to determine if the user has permission |
| 259 to perform some action:: | 244 to perform some action:: |
| 335 | 320 |
| 336 Anonymous Users | 321 Anonymous Users |
| 337 --------------- | 322 --------------- |
| 338 | 323 |
| 339 The "anonymous" user must always exist, and defines the access permissions for | 324 The "anonymous" user must always exist, and defines the access permissions for |
| 340 anonymous users. The three ANONYMOUS_ configuration variables are subsumed by | 325 anonymous users. The three ``ANONYMOUS_`` configuration variables are |
| 341 this new functionality. | 326 subsumed by this new functionality. |
| 342 | 327 |
| 343 | 328 |
| 344 Action | 329 Action |
| 345 ====== | 330 ====== |
| 346 | 331 |
