Non-superuser access to Django Admin - django

I'd like to restrict which parts of the admin interface are visibile to which staff members - for example, one person might be responsible for only billing related items, another only for customer support, and a third might have full access.
I can provide full access by setting is_superuser to True, but I don't think I want that (I don't want all staff with access to the Admin interface to be super users).
I can allow staff members login to the Admin interface by setting is_staff to True, but once logged in the staff member doesn't have access to anything - they see "You don't have permission to edit anything'.
I tried the method described in this question but I'm getting the same "You don't have permission" result:
class MyAdmin(admin.ModelAdmin):
def has_edit_permission(self, request):
return True
Is there a way to have staff members be able to access parts of the Django admin interface without being superuser?

There's no such thing as has_edit_permission. It's has_change_permission.
For more info on the three permission methods, see the Django ModelAdmin docs:
ModelAdmin.has_add_permission(self, request)
Should return True if adding an object is permitted, False otherwise.
ModelAdmin.has_change_permission(self, request, obj=None)
Should return True if editing obj is permitted, False otherwise. If obj is None, should return True or False to indicate whether editing of objects of this type is permitted in general (e.g., False will be interpreted as meaning that the current user is not permitted to edit any object of this type).
ModelAdmin.has_delete_permission(self, request, obj=None)
Should return True if deleting obj is permitted, False otherwise. If obj is None, should return True or False to indicate whether deleting objects of this type is permitted in general (e.g., False will be interpreted as meaning that the current user is not permitted to delete any object of this type).

For what you are wanting to do, don't override has_change_permission - just give the user(s) and/or user group(s) the corresponding permission ("Can change Xs") in addition to checking "is staff".

Related

Separate fields for Users and admins in Django models.py

I have a BooleanField in my models.py file.
I want it to be True for all Admins/Superusers by default, while I want it to be False for all other users by default.
I don't want to use if-else template tags in my html for this purpose, and I am hoping to get a more cleaner solution.
Something like:
field_name = models.BooleanField(
if author.is_superuser:
default = True
else:
default=False
)
Any help is appreciated.
Here the author is the author of the 'Post' which is the model class.
Edit 1: The user.is_superuser which I need is actually the author's user. I need to verify whether the author of a Blog post is a superuser or not, and then assign the default value for the Boolean field.
You don't have any notion of a "current user" in a model definition. But you do have access to the current user in your views (as request.user) so you can use it there to pass the proper initial value for your field
as an example (using function based view):
def myview(request, ....):
if request.method == "POST":
# ...
else:
form = YourModelForm(initial={"field_name": request.user.is_superuser})
EDIT
I don't need the user, but the author's user
What can I say ? If you want better answers, write better questions - you didn't put any context in your question, not even the relevan parts of your model.
This being said, model fields default values are only used in two cases: when creating a new instance, and when adding a new fields to an existing model.
In the first case, your Article or whatever model instance doesn't exist yet, so it cannot have an "author" yet. IOW the "author" is either the request user (most common case and very probably yours), or some other user you explicitely provide. In both cases you do have the right user instance at hand and my answer above applies (either as is or with some adaptation that you're suppoed to be able to do by yourself).
In the second case, that's something you deal with with a data migration, quite simply.

Django: Creating permissions that relate two `User` objects together

Is there any way to set up a permissions system where permissions relate User objects together, i.e. where one User may have the permission to read another User's info (but not necessarily the other way around)? I've read the documentation but it's sparse and from what I can tell permissions are not capable of handling dynamic use-cases.
Basically, I want a permission system that determines what two+ model objects can "do" to each other.
Bonus points if you have any input on how to integrate this into Django Rest Framework.
One approach is to override the BasePermission class to create your custom permission. You can specify the access permission using an extra field in the User model.
class UserPermission(BasePermission):
def has_permission(self, request, view):
is_allowed_user = False
try:
permission = Permission.objects.get(user=request.user.id, user1=request.GET.get('user'))
if permission.is_read_enabled:
is_allowed_user = True
else
is_allowed_user = False
except Permission.DoesNotExist as e:
is_allowed_user = False
return is_allowed_user
Create a model to specify the Permissions
class Permission(models.Model):
user = models.ForeignKey(User,...)
user1 = models.ForeignKey(User,...)
is_read_enabled = models.BooleanField(defualt=False)
Add this permission to view as needed.

Django: Object level permissions DRY

Object level permissions
Example from http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/#object-level-permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit it.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions are only allowed to the owner of the snippet.
return obj.owner == request.user
My need: Queryset of all objects a user can edit
I want to have a django-orm queryset which contains all objects which a given user can edit.
I guess I could solve this by creating a complex django-orm filter (with OR and distinct)
Not DRY
But that's not DRY. That's not DRY because I need to code the stuff twice. One time in has_object_permission() and one time in the django-orm filter.
Question
How to solve my need (queryset of all objects a user can edit) without duplication the permission checking?
If you want that hard to keep things DRY, you'll have to load the entire database entries and apply permission check to every one.
I doubt that's what you really want.
Sometime you can't keep things DRY.
It's the same when you display data to a user. You'll usually apply basic permissions implicitly when performing the query and then ensure the full permissions are valid or not.

User/Group permission class

I want to create a single class, UserGroup, that will contain Users and Groups. In the end I want to be able to give permission to some task based on whether the given User is in the Users M2M or is in the Groups M2M. I understand there are permissions in the Groups but I want to be able to give Permission to a single user (possibly) and I want a consistent interface. The class definition is (I have actually defined Member as User):
class UserGroup( models.Model ):
users = models.ManyToManyField( Member )
groups = models.ManyToManyField( Group )
And then in my views.py I think I will have something like:
def is_in( member ):
## Check to see if they are in the User m2m
if members.objects.filter(pk=member.id).exists():
return True
## Check to see if they are in the Group m2m
if <something>:
return True
## Otherwise return false.
return False
I think this makes sense. What I am not sure of is an efficient method of checking to see if the member is in one of the groups in the Groups M2M.
(And if anyone wants to give me constructive comments on the whole class I would be happy to takes those too).
Django's admin interface and base User model already allows for this. Users can be added to groups and both groups/users can be given permissions. If you have extra needs beyond what is built-in you can start to override User or Group model methods.
In Django, how do I check if a user is in a certain group?
User groups and permissions
When viewing the User object in your admin, see the User Permissions sections. These are settings you can set per user that override the permissions set for the user by their group memberships.

Django admin -- restricting access by user

I was wondering if the django admin page can be used for external users.
Let's say that I have these models:
class Publisher(models.Model):
admin_user = models.ForeignKey(Admin.User)
..
class Publication(models.Model):
publisher = models.ForeignKey(Publisher)
..
I'm not exactly sure what admin_user would be -- perhaps it could be the email of an admin user?
Anyways. Is there a way allow an admin user to only add/edit/delete Publications whose publisher is associated with that admin user?
-Thanks!
-Chris
If you need finer-grained permissions in your own applications, it should be noted that Django's administrative application supports this, via the following methods which can be overridden on subclasses of ModelAdmin. Note that all of these methods receive the current HttpRequest object as an argument, allowing for customization based on the specific authenticated user:
queryset(self, request): Should return a QuerySet for use in the admin's list of objects for a model. Objects not present in this QuerySet will not be shown.
has_add_permission(self, request): Should return True if adding an object is permitted, False otherwise.
has_change_permission(self, request, obj=None): Should return True if editing obj is permitted, False otherwise. If obj is None, should return True or False to indicate whether editing of objects of this type is permitted in general (e.g., if False will be interpreted as meaning that the current user is not permitted to edit any object of this type).
has_delete_permission(self, request, obj=None): Should return True if deleting obj is permitted, False otherwise. If obj is None, should return True or False to indicate whether deleting objects of this type is permitted in general (e.g., if False will be interpreted as meaning that the current user is not permitted to delete any object of this type).
[django.com]
I see chris's answer was useful at the time question was asked.
But now it's almost 2016 and I guess it gets more easier to enable restricted access of Django Admin panel to end user.
Django authentication system provides:
Groups: A generic way of applying labels and permissions to more than one user.
Where one can add specific permissions and apply that group to user via admin panel or with writing codes.
After adding user to those specific groups, Admin need to enable is_staff flag for those users.
User will be able access restricted registered models in admin.
I hope this helps.
django admin can, to a certain extent, be restricted. For a given user, first, they must have admin rights in order to log into the admin site. Anyone with this flag set can view all admin pages. If you want to restrict viewing, you're out of luck, because that just isn't implemented. From there, each user has a host of permissions, for create, update and delete, for each model in the admin site. The most convenient way to handle this is to create groups, and then assign permissions to the groups.