Listing user associated permission in django 2.2.5 - python

I want to list all the permissions that my user has be it a custom permission or default permission
what I have tried till now
request.user.user_permissions
request.user.get_all_permissions
permissions = Permission.objects.filter(user=request.user)
But none of them returned any permissions though the user was a superuser, staff and active
Any lead and help will be great

An admin user normally has no permissions assigned to them, the .has_perm(…) [Django-doc] will always return True, or as the documentation says:
Returns True if the user has the specified permission, where perm is in the format "<app label>.<permission codename>". (see documentation on permissions). If the user is inactive, this method will always return False. For an active superuser, this method will always return True.
So the admin user is not assigned all permissions (this would also be "error-prone" since later new permissions can pop up, and it would thus require extra logic to add these to the superusers that already exist.

Related

How to create Workspaces and manage them for all the users in Django?

I have a complete Login and Registration system in my Django app, that lets me register users, log in users, logout users, change passwords, reset passwords, invite users. I have all the basic functionality.
I want now to have Workspaces for users, as per following points:
There will be a workspace admin of each workspace.
Workspace admins can only add/remove (register/delete) users to his own workspaces.
Users can react to (log in to) only those workspaces to which they have been added.
A superuser (main admin) can manage all workspaces, all workspaces-admins and all users.
How do I accomplish this? You can say this is similar to a Slack thing. I just need a guidelines/roadmap and I will implement it myself.
I have already created a Workspace Model, which looks like below:
class Workspace(models.Model):
name = models.CharField(max_length=254)
created_at = models.DateTimeField(auto_now_add=True)
def make_admin(self, user):
user.is_workspace_admin = True
user.save()
def remove_admin(self, user):
user.is_workspace_admin = False
user.save()
and my User model has following two attributes beside other default Django fields:
class User(AbstractBaseUser, PermissionsMixin):
is_workspace_admin = models.BooleanField(default=True)
workspaces = models.ManyToManyField(Workspace)
Is this approach correct? If not please guide me to the proper way. BTW, using this approach, I can add/assign workspaces to any user, but how will I be able to manage the users logging in their own workspaces and reacting with only their workspaces to which they have been assigned. And also workspaces admins controlling their workspaces’ users etc?
I know about using Groups. So let's say I create all relevant permissions (Can you also tell me how to create permissions?) to add workspace user, remove workspace user, make workspace user a workspace admin, remove workspace admin from workspace adminship etc. and create different Groups and add relevant permissions in each group. Suppose my groups looks like manage_workspace_a to manage (add/remove) the workspace users groups, manage_workspace_admins to manage (add/remove) workspace admins, and default permissions that Django provides for each Model.
So, how will i be able to have the functionality that when a "User A" that has is_superuser=True, makes the is_workspace_admin=True of "User B", then "User B" should automatically gets all the Workspace Admin Permissions. Something like this:
workspace_user = User.objects.get(email="some-email-address")
if request.user.is_superuser:
wordspace_user.permissions.add([Workspace Admin Permissions])
Can somebody explain the whole process with a small code example?
This is a very long, multi-part question but hopefully I can point you in the right direction
I would suggest adding another Many-to-Many field on your User model that handles administrator status. At the moment, you have it set to Boolean flag - so an administrator can either manage all workspaces or none.
Personally, I would reverse the M2M status and put users and administrators on the workspace, rather than on the user model. It's not problematic to have on the user model but I feel it makes more sense to check that the user is in the workspace's permitted users/admins rather than the workspace is in the user's list of workspaces and admin workspaces.
You will need to change your code that adds an administrator to a workspace as you won't want to use a boolean flag:
def make_admin(self, user):
self.administrators.add(user)
As to how you manage the workspace itself, you can just put ORM filters at the very start of your relevant views:
def workspace_view(request, workspace_id):
workspace = get_object_or_404(Workspace, workspace_id)
if request.user not in workspace.users:
return redirect(...)
...the rest of your view
Bear in mind that this doesn't allow administrators in unless they are in the users group - you will either need to add them to users or add another condition to check if they are in administrators.
If you want an overview of all the workspaces in some sort of index/home page, you would just use the m2m reverse accessor which depends on your reverse name (or /relation/_set by default):
def workspaces(request):
workspaces = request.user.workspaces.all()
You can definitely leverage Django's in-built permissions system, I would point you to the documentation because that is a long subject:
https://docs.djangoproject.com/en/4.0/topics/auth/default/#permissions-and-authorization

Why does the admin site not care about my custom user's permissions?

I started a Django (1.10.3) project with a custom user model, inherited from AbstractBaseUser. A couple of weeks into developing the thing, I saw that I needed more granular permissions for admin users, so I extended my user model with PermissionsMixin, generated and applied migrations, and updated my ModelAdmin.
To try it out I logged in to the admin with my superuser and created a new user with all permissions added manually. When I logged in with that new user, I was greeted by a nice "You don't have permission to edit anything".
So I went to the shell, checked my user's permissions and they were there.
>>> u = User.objects.get(username='new_user')
>>> u.get_all_permissions()
{'admin.add_logentry', ...}
However,
>>> u.has_perm('admin.add_logentry')
False
Now, what has_perm does, if the user is not an active superuser, is to call this:
def _user_has_perm(user, perm, obj):
for backend in auth.get_backends():
if not hasattr(backend, 'has_perm'):
continue
try:
if backend.has_perm(user, perm, obj):
return True
except PermissionDenied:
return False
return False
But,
>>> from django.contrib.auth import get_backends
>>> backend = get_backends()[0] # django.contrib.auth.backends.ModelBackend
>>> backend.has_perm(u, 'admin.add_logentry')
True
So,
Why are user.has_perm(perm) and backend.has_perm(user, perm) returning different values?
And ultimately, how can I get the permissions system to work correctly in this scenario?
I should be ashamed of the actual answer to this. At least I hope there's a lesson to be learned from it. Maybe I can add something along the lines of "always check your own implementations first" to my bug fixing heuristics.
The apparent impossibility of those two methods returning different things led me to inspect if I was actually calling them. It turns out that I completely forgot my own implementation of has_perm, which I absent mindedly created in order for the user model to be compliant with the admin.
This implementation, of course, only checked for superuser status.
I think that Occam fellow was on to something.

Remove user's permissions (django)

I have an issue with removing permissions to users in view or even in the shell. Let me explain my problem:
I did those tests in the shell:
org = Organisateur.objects.get(user__username__contains="ghj")
content_type = ContentType.objects.get_for_model(Tournoi)
Tournoi is the name of a model
permission_ecriture = 'ecriture_Palaiseau'
permission = Permission.objects.get(content_type=content_type, codename=permission_ecriture)
org.user.user_permissions.remove(permission)`
but when I write:
org.user.has_perm('inscription.ecriture_Palaiseau')`
it returns True
but when I rewrite:
org = Organisateur.objects.get(user__username__contains="ghj")
org.user.has_perm('inscription.ecriture_Palaiseau')`
it returns False
It is really weird. Why does it works like this?
In my views, it seems that the permissions are not removed even if I do write:
org = Organisateur.objects.get(user__username__contains="ghj")
(after removing the permission, the user still has it)
What I want to do is to remove a permission from an user and add another permission to the same user immediately after.
But each time I do that, the user still has the "removed permission"......
Thank you very much
I look forward to hearing from you all soon.
This behavior is expected because permissions are cached. From the Django docs:
Permission caching
The ModelBackend caches permissions on the User object after the first time they need to be fetched for a permissions check. This is typically fine for the request-response cycle since permissions are not typically checked immediately after they are added (in the admin, for example). If you are adding permissions and checking them immediately afterward, in a test or view for example, the easiest solution is to re-fetch the User from the database.
Your code is almost right, you just have forgotten to save your user object at the end!
use user.save()

Making group in django app.

I am making an app. In which multiple superusers are there and beneath these super user we have multiple user. I am able to make superuser.But I am not able to add user in that for that super user.I am relatively new in django.
Superusers are special as their permission system returns True on every permission request (it is hardcoded). There is no "super group". You can simply create a group and give it all permissions (so add, change and delete permission to every model).

removing buttons/links in django admin

I have an apps and I am making used of django admin, but my apps does not allow deleting of data and django admin have a delete button/link. I have already removed the delete action.
my question is, how can i remove the delete button/link in admin page in django?
class MyAdmin(ModelAdmin):
def get_actions(self, request):
actions = super(MyAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
If the delete permission is not given the "Delete" button of a single object will disappear. The changelist "action" (select list to apply to objects with checkbox checked) will still be shown because you may have the permission to delete some of the objects. You can remove both with the above code.
CLARIFICATION (for the downvoters): admin checks if the current user has the permission to delete and then shows/hides the button/s accordingly. You wrote "my apps does not allow deleting" so I assumed you took away permissions. A superuser does not get looked up in permissions, superuser always returns "yes I have that permission". If you want the buttons to disappear for superusers, you have to use my above code. For other users just take away the permission as per Secator's answer.
Do not remove or change anything in the admin.
Instead remove user's/group's permission to delete given model. If user does not have the permission to delete, the delete button won't appear at any page related to that model.

Categories

Resources