Restructure django.contrib.auth, make Models replaceable
|Reported by:||Owned by:||Adrian Holovaty|
|Severity:||Keywords:||auth rewrite replace models|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
I'm currently not very happy with the current auth-module. It mixed three different things I think:
- API for user-authentication and permission-checks
- implementation of user-system
- implementation of permission-system
The problem is, that you cannot replace parts of this system, without replacing everything (and ending in having to write a new auth-system thats incompatible with some generic_views, the admin, ...). So I think this parts should be separated and some generic-API should be created.
Btw.: I was told, that there was a bug for this problem, but I didn't find it, sorry.
I think that should be separated into three apps. Some generic API should be used to authenticate the user and check permissions. The implementation of the real models/checks should be done in separate applications that can be replaced (so you would be able to replace the user-model for example).
If doing so I suggest dropping the current backends-implementation, because it may break things. The problem is that request.user is filles by these backends and as backends may return objects that are not django.contrib.auth.models.User code will fail that needs that class (-> foreign keys). So I think one user-model should be used, and only one. Backends could be done by using some user-model that saved some type and id and wrapps the real user-object, if backends are really needed. This has the advantage of one user-model that can be used in your models for foreign keys.
As some(/many) code depends on the current auth-models this must be rewritten (this is probably the most annoying part), as an example the create_update-generic-views use the message-system and user.is_authenticated(). Some user-API could be defined as a standard for such cases.
Perhaps the message-system should get it's own application, as many users like and use this.
Possible contributions by me so far
I started creating a auth-replacement for the first part (the API), while trying to keep the current API where possible.
- http://groups.google.com/group/django-developers/msg/623ad2f878d9ebde?hl=en& (post to django-developers, describing some problems, too)
- https://svn.webmasterpro.de/django-auth-rewrite/django/contrib/newauth/ (branch I created, including a generic API)
The current code includes parts of whats done in the generic-auth/row-level-permissions-branch so far. But no implementation is included, only some API is defined, that can be used.
In the setting-file the user can set two additional options:
- AUTHENTICATION_MODULE: Module used for authentication
- AUTHORIZATION_MODULE: Module used for authorization (aka permission checks)
These modules have to implement some simple API, in detail:
- get_anonymous_user: done as a function, as the user may be saved in the database
- get_user_model: used to create working foreign keys
- login_redirect: redirect to the login (the modules get full control over the views, nothing is implemented in the auth-module so far)
- authenticate: like with the backends
- is_authenticated: moved from the user-object
- has_model_permission: test if a user may access a model
- has_object_permission: test if a user may access an object (may (only) include model-check of course)
- denied_redirect: as above (may just return a HttpResponse, too)
The code includes some decorators and a fork of the middleware/context_processor (with changed import-statements).
The models-file is only used to get the User-model into models (for backwards compability).
I think the code can be written nicer by just importing the functions of the modules (like done with the User-Model), but I haven't tested this yet.
If you are interested in this branch I will continue converting the old models and functionality. ;-)