Code


Version 8 (modified by Chris Long <indirecthit@…>, 8 years ago) (diff)

--

Introduction

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.

What are Row Level Permissions?

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

Why do we need this?

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.

Planned Features

  • Negative permissions, e.g. "User A can not modify article 2 and 4 but can modify all other articles"
  • 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
  • A method of adding row level permissions using an API
  • Allow custom permissions for row level permissions
  • Developer can enable or, by default, disable the row level permissions on an object
  • Generic functions to create row level permissions in certain scenarios, e.g. the above scenerio

Implementation

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.

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.

Timeline

TaskStatusDeadline
Design PlanIn progressJune 10
Row Level Perm object implementationIn progressJune 14
Row Level Perm object testingNot startedJune 17
Enabling/Disabling of row level permsNot startedJune 20
API designNot startedJune 22
API implementationNot startedJuly 3
API testedNot startedTBA
API documentationNot startedTBA
Admin interface modifiedNot startedTBA
Negative row level perms implementedNot startedTBA
Negative row level perms testedNot startedTBA
Generic Functions to create row level permsNot startedTBA
Documentation and tutorial writtenNot startedTBA

Deliverables

  • Modified administration interface that will allow users to modify row level permissions
  • API to allow developers to modify the row level permissions
  • Ability of developer to enable or disable row level permissions
  • Changes to the generated SQL that will create the row level permission table
  • Tests for all the above

Contact

Please contact me (indirecthit at gmail.com) or modify this page with any comments you have on what I have written above.

Suggestions

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.

  • 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
  • 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).
  • From oggie rob:
    • "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"
    • "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)."
  • 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."
  • 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.
  • 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."