Changes between Version 11 and Version 12 of RowLevelPermissions


Ignore:
Timestamp:
Jul 13, 2006, 6:21:11 PM (18 years ago)
Author:
Chris Long <indirecthit@…>
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • RowLevelPermissions

    v11 v12  
     1[[TOC(inline)]]
     2
    13== Introduction ==
    24
    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? ===
    76
    87An 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".
    98
    10 == Why do we need this? ==
     9=== Why do we need this? ===
    1110
    1211An 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.
    1312
     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)
    1417
    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 ==
    2319
     20=== Basic Idea ===
    2421
    25 == Implementation ==
     22There 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.
    2626
    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 ===
    2828
    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.
     29Enabling 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.
    3030
    31 == Timeline ==
     31Example: To enable row level permissions for the mineral model, the model would look like:
     32{{{
     33#!python
     34class 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}}}
    3248
    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 ===
    4750
     51The 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...
     55rlp_list = quartz.row_level_permissions.all()
     56...
     57}}}
    4858
    49 == Deliverables ==
     59=== Accessing the Owner and Model of a Row Level Permission ===
    5060
    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
     61To return the owner of a row level permission use the attribute "owner". For example:
     62{{{
     63#!python
     64...
     65user = row_level_permission.owner
     66...
     67}}}
    5668
     69To return the instance of a row level permission use the attribte "type". For example:
     70{{{
     71#!python
     72...
     73object = 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.''
    5777
    58 == Contact ==
     78=== Creating a Row Level Permission ===
    5979
    60 Please contact me (indirecthit at gmail.com) or modify this page with any comments you have on what I have written above.
     80There are two helper methods to create row level permissions. These can be accessed by using the Row Level Permissions manager (e.g. RowLevelPermission.objects)
    6181
     82The first is create_row_level_permission:
     83{{{
     84#!python
     85def create_row_level_permission(self, object_instance, owner_instance, permission, negative=False):
     86   ...
     87}}}
     88The 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.''
    6290
    63 == Suggestions ==
     91The second is create_default_row_permissions:
     92{{{
     93#!python
     94def create_default_row_level_permissions(self, object_instance, owner_instance, change=True, delete=True, negChange=False, negDel=False):
     95   ...
     96}}}
     97This 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...
     101RowLevelPermissions.objects.create_default_row_level_permissions(quartz, user, delete=False)
     102...
     103}}}
    64104
    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 ===
    66106
    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."''
     107This will be integrated into the GenericAuthorization SoC project. More info to come.
     108
     109== Implementation Notes ==
     110
     111Please see RowLevelPermissionsDeveloper for more information on how row level permissions are implemented.
     112
     113== Download ==
     114
     115Row 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.
Back to Top