Code

Changes between Version 35 and Version 36 of RowLevelPermissions


Ignore:
Timestamp:
11/23/06 19:54:54 (7 years ago)
Author:
adrian
Comment:

Made some edits. Still working on it.

Legend:

Unmodified
Added
Removed
Modified
  • RowLevelPermissions

    v35 v36  
     1= Row-level permissions = 
     2 
    13== Introduction == 
    24 
    3 === What are Row Level Permissions? === 
    4  
    5 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". 
     5=== What are row-level permissions? === 
     6 
     7Some examples of row-level permissions: "User A has read-access to article 234" or "User D has read, write access to article 234." 
    68 
    79=== Why do we need this? === 
    810 
    9 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. 
    10  
    11 == Using Row Level Permissions == 
    12  
    13 === Basic Idea === 
    14  
    15 There are a few things you need to know about row level permissions before working with them: 
    16  
    17  * Row level permissions use the permissions table to determine an object's possible permissions, you need to create permissions in the permissions table before using them in row level permissions. 
    18  * Row level permissions can be negative, this is determined by an attribute called "negative".  
    19  * The order of checking permissions will work in the following order: User Row Level Permission -> Group Row Level Permission -> User Model 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 (or false). 
    20  
    21 === Enabling Row Level Permissions === 
    22  
    23 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. 
    24  
    25 Example: To enable row level permissions for the mineral model, the model would look like: 
     11With the current permission system, a user of Django's admin interface is capable either of editing *all* objects of a certain type or editing *none* of the objects of a certain type. After implementing a row level permission, the user can be capable of editing only certain objects of that type -- e.g., just the objects he created himself. 
     12 
     13=== Status in Django === 
     14 
     15Row-level permissions are being implemented in a branch -- the [http://code.djangoproject.com/browser/django/branches/per-object-permissions per-object-permissions branch]. This branch needs your help in testing. To get the code, use this Subversion command: 
     16 
     17{{{ 
     18svn co http://code.djangoproject.com/svn/django/branches/per-object-permissions 
     19}}} 
     20 
     21== Using row-level permissions == 
     22 
     23=== The basics === 
     24 
     25There are a few things you need to know about row-level permissions before working with them: 
     26 
     27 * Row-level permissions use the permissions table to determine an object's possible permissions. You need to create permissions in the permissions table before using them in row-level permissions. 
     28 * Row-level permissions can be negative. This is determined by an attribute called "negative." 
     29 * Django checks permissions in the following order: 
     30   * User row-level permission 
     31   * Group row-level permission 
     32   * User model-level permission 
     33   * Group model-level permission 
     34   The checking stops either at the first positive or negative. If no permission is found, it will return a negative (or false). 
     35 
     36=== Enabling row-level permissions === 
     37 
     38To enable row-level permissions for a model, add a {{{row_level_permissions = True}}} to the model's {{{class Meta}}}. By default, row-level permissions are disabled. 
     39 
     40For example: 
     41 
    2642{{{ 
    2743#!python 
     
    3248    class Admin: 
    3349        pass 
    34      
     50 
    3551    class Meta: 
    36         unique_together = (('name', 'hardness'),) 
    3752        row_level_permissions = True 
    38    
     53 
    3954    def __str__(self): 
    4055        return self.name 
    4156}}} 
    4257 
    43 You do not need the ''class Admin'' but it does create the default change, add and delete permissions for the object which are useful to have. 
    44  
    45 === Creating a Row Level Permission === 
    46  
    47 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) 
    48  
    49 The first is create_row_level_permission: 
     58The {{{class Admin}}} is not required, but its presence does create the default add/change/delete model-level permissions, which are useful to have. 
     59 
     60=== Creating a row-level permission === 
     61 
     62Django has two helper methods for use in creating row-level permissions. They both live on the {{{RowLevelPermission}}} model manager (i.e., {{{RowLevelPermission.objects}}}). 
     63 
     64The first helper function is {{{create_row_level_permission}}}: 
     65 
    5066{{{ 
    5167#!python 
    5268def create_row_level_permission(self, object_instance, owner_instance, permission, negative=False): 
    53    ... 
    54 }}} 
    55 The permission parameter can either be the codename of the permission or a permission instance. The negative parameter is optional and will default to false. You must pass an instance of the object and owner to this method. 
    56  
    57 The second is create_default_row_permissions: 
     69   # ... 
     70}}} 
     71 
     72The permission parameter can either be the codename of the permission or a permission instance. The negative parameter is optional and defaults to {{{False}}}. You must pass an instance of the object and owner to this method. 
     73 
     74The second helper function is {{{create_default_row_permissions}}}: 
     75 
    5876{{{ 
    5977#!python 
    6078def create_default_row_level_permissions(self, object_instance, owner_instance, change=True, delete=True, negChange=False, negDel=False): 
    61    ... 
    62 }}} 
    63 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.  
    64  
    65 An example of its use, this creates a change row level permission on the quartz object: 
    66 {{{ 
    67 #!python 
    68 ... 
    69 RowLevelPermissions.objects.create_default_row_level_permissions(quartz, user, delete=False) 
    70 ... 
    71 }}} 
    72  
    73 === Checking Permissions === 
    74  
    75 GenericAuthorization and row level permissions will eventually be merged. Therefore, I have shown two different methods of checking for permissions, one using the generic authorization and the currently implemented technique. 
    76  
    77 The current method uses the has_perm method in the User model. Note: The object parameter is optional, this is to allow backwards compatibility, so if you do not want to check for row level permissions do not include the object parameter. 
    78  
    79 Example: 
    80 {{{ 
    81 #!python 
    82 ... 
     79   # ... 
     80}}} 
     81 
     82This will set up a row-level permission with the default permissions set up for an object. The default permissions are: add, change and delete. 
     83 
     84For example, this creates a change row-level permission on the {{{quartz}}} object: 
     85 
     86{{{ 
     87#!python 
     88RowLevelPermission.objects.create_default_row_level_permissions(quartz, user, delete=False) 
     89}}} 
     90 
     91=== Checking permissions === 
     92 
     93To check whether a user has permission to edit an object, use the {{{has_perm()}}} method on the {{{User}}} object: 
     94 
     95{{{ 
     96#!python 
    8397user.has_perm("mine.can_mine", object=mineral) 
    84 ... 
    85 }}} 
    86  
    87 This will return either True or False depending on if the user has the correct permission. It will return false if the user has a negative row level permission on the object.  
    88  
    89 This will also check group row level permissions. If the user is in two groups, the first having a positive row level permission and the second having a negative row level permission, it will take the positive row level permission over the negative. 
    90  
    91 '''Second method using GenericAuthorization will be written after the merge. It will follow the documentation written on GenericAuthorization''' 
    92  
    93 ==== Has Row Level Permission ==== 
    94  
    95 The method contains_permission checks if the user has the given permission on a model (not an instance of a model but the model). This checks if there is exists the given row level permission on any of the instances of the model. It is used in the admin interface to determine if the change list should be shown to the user. 
    96  
    97 E.g. If user A has change permission on article 234, and you did: 
    98 {{{ 
    99 #!python 
    100 ... 
    101 userA.contains_permission("mine.change_mineral", Mineral) 
     98}}} 
     99 
     100The {{{object}}} parameter is optional for backwards-compatibility. If you don't want to check row-level permissions, exclude the {{{object}}} parameter. 
     101 
     102{{{has_perm()}}} returns either {{{True}}} or {{{False}}}. It returns {{{False}}} if the user has a negative row-level permission on the object. It also checks group row-level permissions. If the user is in two groups, the first having a positive row-level permission and the second having a negative row-level permission, it will take the positive permission over the negative. 
     103 
     104Note that the GenericAuthorization branch (yet another of Django's many current branches) implements a different way of checking permissions. See the GenericAuthorization page for how row-level permissions fit in with that scheme. 
     105 
     106==== Has row-level permission ==== 
     107 
     108The method {{{contains_permission()}}} checks whether the user has the given permission on a model -- not an *instance* of a model but the model itself. This checks if there is exists the given row level permission on any of the instances of the model. It is used in the admin interface to determine if the change list should be shown to the user. 
     109 
     110E.g. If {{{some_user}}} has change permission on article 234, and you did: 
     111{{{ 
     112#!python 
     113... 
     114some_user.contains_permission("mine.change_mineral", Mineral) 
    102115... 
    103116}}}