Django AdminSite/ModelAdmin for end users? Django AdminSite/ModelAdmin for end users? django django

Django AdminSite/ModelAdmin for end users?


There is nothing inherently special about admin. It behaves just like any other view. So if it is using permissions to determine access (for example, if you set a user's .is_staff to True but give them access only to specific permissions) then it will be equally secure to any view you might create that uses permissions to determine access.

In the same vein, the customization you provide to a ModelAdmin is going to result in an implementation that is equally secure as anything you might write.

If you write a custom has_change_permission for your your model, for example:

def has_change_permission(self, request, obj=None):    return obj.company == request.user.get_profile().company

This is going to work. It's not going to merely hide a button; it's going to completely block this object from being edited.

The people who wrote django.contrib.admin did not write it with the assumption that anyone with an is_staff = True could be trusted as much as a superuser, or was stupid enough to never take a look at the source code of a web page. Although writing your own views is encouraged, it is still a robust interface.

See, for example, this section of the source code which raises a PermissionDenied exception if you try to access the change_view without permission to edit the actual object:

def change_view(self, request, object_id, extra_context=None):    "The 'change' admin view for this model."    model = self.model    opts = model._meta    obj = self.get_object(request, unquote(object_id))    if not self.has_change_permission(request, obj):        raise PermissionDenied    # view continues...

So even if someone were to craft the correct URL to edit a given object, so long as you had correctly implemented has_change_permission the user will be denied access.


We have a system that just runs as you asked.

Program have a basic user login, which is tha basic site and uses hand written views and templates (as it needed to be)... There eexists a Customer part, which is the basic admin page with limited access rights. And there is admin whom are me and people like me.

Logic is, admins are people working in the company, who may have all access permissions (superusers as sjango said) or limited access to the applications but can see all related DB records from those they have access. Customers are people who we sell our program, they have limited access to the admin and can only see records related to them. users are customers of our costumers...

In that point, django permissions are not sufficient, because our customer must see record belong to his account, while a standard admin can see all records. These two can reach applications according to their permissions. Superuser can see and do anything...

For the solution, instead of usnig django site application (which i never used and do not have much information) we created a model that extends Django user, which have a field like role is user role is System administrator, then he can see everything (if superuser, otherwise he uses permissions as normal)... If not, he can reach records relatred to their website (Company in your situation).

So, nearly each database table must have a foreignkey defining owner company of the related record.

By that, you can filter records belong to a specific company if required...

In my models, i have Kullanici that inherits User model

class Kullanici(User):    rol = SmallIntegerField()# 1 if system admin, 2 if cusotmer etc...

Then, i write a few methods to that overrides admin methods, like ;ModelAdmin.save and modelAdmin.queryset that do the following check...

#override admin queryset methoddef override_queryset(obj, req):    qs = super(type(obj), obj).queryset(req)    kullanici = Kullanici.objects.get(id=req.user.id)    if kullanici.rol == 10:        return qs    return qs.filter(site=kullanici.site)

So, when a user go to list view of an application, he only sees sites related to him, other records will not be shown, or he will get permisson error if he tries to go to a record belong to some other site. These are all django bassed controls, so you can be sure they will not reach ant record that they must not.

You must override all Admin methods that require filtering belong to customer.

For further limitation i used a function to show/hide fields of the model. In the admin .py file:

class SomeModelAdmin(ModelAdmin):    exclude= []    def changelist_view(self, request, extra_context=None):        extra_context = {'exclude':['field1','field2']}        return get_admin_listview(self, request, extra_context)def get_admin_listview(obj, req, extra):system_admin = Kullanici.objects.get(id=req.user.id).rol == 1if not system_admin:    if 'exclude' in extra.keys():        for key in extra['exclude']:            if key not in obj.exclude:                obj.exclude.add(key)

you give a list of field names to be hidden, and it will hide them if user is not system admin...

Handycaps are, django admin caching may cause, which happened to me once or twice in 8 months. Other important part is, you can not limit admin filters, so if you have a filter that requred limited access, you can not filter the filter keys. You can either display it with all options or simply do not use it.

If this approach solves your problem, i may write a more detailed information...

UPDATE: Yes, permission system is simple and secure, if you check the source code of permission_required decorator from the latest trunk code...

Logic is simple, the user has relevant permisson, related view is ececuted. Otherwise related view or code is not executed at all. So, permissons provides enough security for django admin. Permission control can be be used both on view level and/or template level.

One point that must be carefull is hand written views, where insecure code might cause serious problems, but this is all about your coding, and this is the kind of security risk that you will face with on every framework and programming language...

Last point of issue is the filtering mechanism of django and admin view pages. Since Nearly all admin filters uses GET to filter data, and passes id's to urls for displaying a specific record. Seciruty part of django book shows basic information about possible security issues and how django handles them... On the other hand, 22 December 2010 security update shows a such important vulnerability, which requires enough information about model structure.


If the admin - customised using the hooks provided, if necessary - meets your needs, then of course there's no reason not to use it. The point is that you have to be realistic about what it provides and what it doesn't provide, and be certain that you're not going to start needing functionality that is only possible outside the admin. I've been down that road, and it is not pretty.