Changes between Version 11 and Version 12 of RowLevelPermissions
- Timestamp:
- Jul 13, 2006, 6:21:11 PM (18 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
RowLevelPermissions
v11 v12 1 [[TOC(inline)]] 2 1 3 == Introduction == 2 4 3 The summary below is a very basic idea of where I want this to go. Over the next few days, as I explore the Django source code in more depth I will be expanding upon what is written here, and making changes. 4 5 6 == What are Row Level Permissions? == 5 === What are Row Level Permissions? === 7 6 8 7 An example of row level permissions would be: "User A has read-access to article 234" or "User D has read, write access to article 234". 9 8 10 == Why do we need this?==9 === Why do we need this? === 11 10 12 11 An example of where this would be useful is a forum or message board. With the current permission system, a user is capable of editing all the posts or unable to edit any posts. After implementing a row level permission, it can be modified so a user is capable of editing only their own personal posts. 13 12 13 == Todo == 14 ''This is a slightly incomplete list, as of this writing my todo list is unavailable, I'll modify this when I have access to it'' 15 * Adding row level permission editing to admin interface - Started. I have created an application that modifies row level permissions and will be adding this to the administration interface. 16 * Adding checking of row level permissions (so they actually do something) 14 17 15 == Planned Features == 16 17 * Negative permissions, e.g. "User A can not modify article 2 and 4 but can modify all other articles" 18 * A modified admin page for editing objects that will allow admins to add users with specific (negative and positive) row level permissions to the object being edited 19 * A method of adding row level permissions using an API 20 * Allow custom permissions for row level permissions 21 * Developer can enable or, by default, disable the row level permissions on an object 22 * Generic functions to create row level permissions in certain scenarios, e.g. the above scenerio 18 == Using Row Level Permissions == 23 19 20 === Basic Idea === 24 21 25 == Implementation == 22 There are a few things you need to know about row level permissions before working with them: 23 * Row level permissions use the permissions table to determine an objects possible permissions, you need to create permissions in the permissions table before using them in row level permissions. 24 * Row level permissions can be negative, this is determined by an attribute called "negative". 25 * The order of checking permissions will work in the following order: User Row Level Permission -> User Model Level Permission -> Group Row Level Permission -> Group Model Level Permission. The checking will stop either at the first positive or negative, and if no permission is found will return a negative. 26 26 27 The priority of permissions will be modified to follow this order: User Row Level -> Group Row Level -> User Object Type -> Group Object Type. The reason for this change is to allow negative permissions, the permissions code should check in this order, stopping at the first positive permission or negative permission. These modifications will have to be made after discussing them with Joseph Kocherhans who is implementing GenericAuthorization and other members of the development team. 27 === Enabling Row Level Permissions === 28 28 29 The actual database structure of the row level permissions system will use a single table and generic foreign keys. The generic foreign key will be modified slightly from the code written by Luke Plant in his tagging application (http://files.lukeplant.fastmail.fm/public/python/lp_tagging_app_0.1.zip). The changes will most likely consist of changing the primary keys to be integers rather then strings.29 Enabling row level permissions is done by using the Meta class, you enable row level permissions by setting the "row_level_permissions" attribute to true. By default, row level permissions are assumed to be disabled. 30 30 31 == Timeline == 31 Example: To enable row level permissions for the mineral model, the model would look like: 32 {{{ 33 #!python 34 class Mineral(models.Model): 35 name = models.CharField(maxlength=150) 36 hardness = models.PositiveSmallIntegerField() 37 38 class Admin: 39 pass 40 41 class Meta: 42 unique_together = (('name', 'hardness'),) 43 row_level_permissions = True 44 45 def __str__(self): 46 return self.name 47 }}} 32 48 33 ||'''Task'''||'''Status'''||'''Deadline'''|| 34 ||Design Plan||Complete||June 10|| 35 ||Row Level Perm object implementation||Complete||June 14|| 36 ||Row Level Perm object testing||In progress||June 17|| 37 ||Enabling/Disabling of row level perms||In progress||June 20|| 38 ||API design||In progress||June 22|| 39 ||API implementation||Not started||July 3|| 40 ||API tested||Not started||TBA|| 41 ||API documentation||Not started||TBA|| 42 ||Admin interface modified||Not started||TBA|| 43 ||Negative row level perms implemented||Not started||TBA|| 44 ||Negative row level perms tested||Not started||TBA|| 45 ||Generic Functions to create row level perms||Not started||TBA|| 46 ||Documentation and tutorial written||Not started||TBA|| 49 === Accessing Row Level Permissions from a Model === 47 50 51 The relation name for row level permissions from a model is "row_level_permissions", this will return all row level permissions related to the instance of the object. For example, this will return all row level permissions related to the object quartz: 52 {{{ 53 #!python 54 ... 55 rlp_list = quartz.row_level_permissions.all() 56 ... 57 }}} 48 58 49 == Deliverables==59 === Accessing the Owner and Model of a Row Level Permission === 50 60 51 * Modified administration interface that will allow users to modify row level permissions 52 * API to allow developers to modify the row level permissions 53 * Ability of developer to enable or disable row level permissions 54 * Changes to the generated SQL that will create the row level permission table 55 * Tests for all the above 61 To return the owner of a row level permission use the attribute "owner". For example: 62 {{{ 63 #!python 64 ... 65 user = row_level_permission.owner 66 ... 67 }}} 56 68 69 To return the instance of a row level permission use the attribte "type". For example: 70 {{{ 71 #!python 72 ... 73 object = row_level_permission.type 74 ... 75 }}} 76 ''Developer's note: This will most likely change as I'm not too sure "type" accurately describes what it represents. I will update this page when I make the change.'' 57 77 58 == Contact==78 === Creating a Row Level Permission === 59 79 60 Please contact me (indirecthit at gmail.com) or modify this page with any comments you have on what I have written above. 80 There are two helper methods to create row level permissions. These can be accessed by using the Row Level Permissions manager (e.g. RowLevelPermission.objects) 61 81 82 The first is create_row_level_permission: 83 {{{ 84 #!python 85 def create_row_level_permission(self, object_instance, owner_instance, permission, negative=False): 86 ... 87 }}} 88 The permission param can either be the codename of the permission or a permission instance. The negative param is optional and will default to false. You must pass an instance of the object and owner to this method. 89 ''Developer's Note: I will probably add in another option to allow the permission to be an id as well.'' 62 90 63 == Suggestions == 91 The second is create_default_row_permissions: 92 {{{ 93 #!python 94 def create_default_row_level_permissions(self, object_instance, owner_instance, change=True, delete=True, negChange=False, negDel=False): 95 ... 96 }}} 97 This will set up a row level permission with the default permissions set up for an object. The default permissions are: add, change and delete. An example of it's use is: 98 {{{ 99 #!python 100 ... 101 RowLevelPermissions.objects.create_default_row_level_permissions(quartz, user, delete=False) 102 ... 103 }}} 64 104 65 From the discussion on Django-developers group. The italicized suggestions I have decided to use or not use, the other ones I am still considering/looking into. 105 === Checking Permissions === 66 106 67 * ''Using GenericForeignKey and one table instead of having a table for each object. Suggested by Ian Holsman. As an example see: http://files.lukeplant.fastmail.fm/public/python/lp_tagging_app_0.1.zip '' 68 * ''Implementing negativity. ie person X is NOT allowed to see row Y. Suggested by Ian Holsman. Suggested by Honza Král to allow something like "person X can read all articles except article Y". This would most likely require a rewrite of the order of permissions, therefore doing it from most specific (row level) to least specific (object type).'' 69 * From oggie rob: 70 * "An alternative approach for the group-level changes: a new permission type that allows you to assign a group that can access that object. i.e. permissionA = access for every user in groupA. Then every user that belongs to groupA can access objects created by any user in groupA. You would then, obviously, add the permission to groupA only" 71 * "How do you deal with those permissions in the generic and admin list views? You may need to change the returned lists to show only those things that the user has created? I'm not sure. I know it would be an issue in the admin pages but the generic lists might be used in various ways (and perhaps the option to choose would be nice)." 72 * ''From Ian Holsman: "while I use integer's as my keys (which is they default Django way), others override this and use strings and other weird things. I'm not sure how my previous suggestion would work when you take that kind of thing into account."'' 73 * ''Generic mechanism for creating row level permissions when enabled, such as the example of the forum given above. E,g. the developer would enable this feature, and from that point on a user would have row level permissions (specified by the developer) for any object they create. Suggested by Andy Shaw.'' 74 * ''From Andy Shaw: "would Luke's GenericForeignKey allow for inline editing, assuming it was to be adopted? Personally I'd much rather be able to alter a row's permissions on its own admin page than have to switch table."'' 107 This will be integrated into the GenericAuthorization SoC project. More info to come. 108 109 == Implementation Notes == 110 111 Please see RowLevelPermissionsDeveloper for more information on how row level permissions are implemented. 112 113 == Download == 114 115 Row Level Permissions are currently hosted in a branch on Django SVN. Please use: ''svn co http://code.djangoproject.com/svn/django/branches/per-object-permissions'' to download the current code. As of July 13, the subversion repository has not been updated. I will be doing this tomorrow once I finish testing my latest changes and additions. Please ignore the attached files as these are old versions of the row level permissions.