Legend:

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.

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:

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.''

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.