Imagine these models:
User has many Buckets and each Bucket has many Items. User A only sees his own list of buckets and items in it. Now, I want to give user B permission to see user's A buckets but not items. Is this possible with Django built-in permission system or I need something like django-guardian for this purpose?
I am new to django and I am a little confused.
Django has two different levels of permissions when it comes to models: model-level and object-level.
Model-level permissions are the default type in Django, and they are enforced by the default permissions backend. They work on an "all or nothing" basis, so a user can either have a permission (such as removing) for all objects of a model, or they don't.
If you are running into a situation where "User A needs to be able to remove any comment" or "User B needs to be able to edit any blog post", you are probably looking for model-level permissions.
Object-level permissions are supported in Django, but they require you to use a third-party permission backend. They work in a similar way to model-level permissions, but instead of being "all or nothing" on all model objects, it is only for a single object. There are many packages out there for object-level permissions, and the one you choose depends on what you need out of the permission backend.
If you are running into a situation where "User A needs to be able to remove only objects where they are the creator" or "User B needs to be able to remove a subset of objects", you are probably looking for object-level permissions.
You appear to be interested in object-level permissions.
Related
If you have django.contrib.auth in your INSTALLED_APPS django will automatically create add, change, delete and view permissions to every model in your system (or any one you add later). These are stored in auth_permission.
In django doc, here is what we can read under Groups section:
django.contrib.auth.models.Group models are a generic way of categorizing users so you can apply permissions, or some other label, to those users. A user can belong to any number of groups.
A user in a group automatically has the permissions granted to that group. For example, if the group 'Site editors' has the permission can_edit_home_page, any user in that group will have that permission.
I've a group with no permission at all (call it NADA) and I've assign that group to a specific user (let's call him Pierre). Pierre can still connect and create, update, delete or view anything on my web interface.
How can I make it working? There's few or no doc on the web for native Django Permission.
I've read this nice publication
django-permission-apps-comparison.
I know I could install django-guardian, django-role-permissions or
django-rules...
I know we can manage access via middleware or decorator But since django IS creating these tables for us (user, groups, permissions and group_permissions)
I thought it was extremely simple to implement CRUD access to any model class!
Wrong?
Do I miss something?
Note: Working with Python3.6 and Django 2.1.3
Django permissions are simple. As far as I understand your question, you are trying to create a user with no permission and he should not see any entries on the Django admin.
First thing is to make sure the user is not marked as "superuser", the superuser sees everything no matter which group they are added in.
If he is not a superuser and is still able to see the model then you should make sure he is not part of multiple groups. If a user is in multiple groups then a union of all permissions is what is applied to them. This link will give you more details on different flags for a user https://djangobook.com/users-groups-permissions/. Let me know if this helps.
Django allows you to give users and groups of users custom permissions on objects (and django-guardian adds some nice ways of using this). There are various ways of putting users into hierarchies. What I'd like to do is add two types of hierarchies to the permissions themselves. For example if someone has a given permission on a Book object, I want them to implicitly have that permission on each Page object. Also, if someone has an change permission on a Page, I want them to implicitly have the view permission on that Page.
In sum, I want page.has_permission('view', user) to check both page.has_permission('*edit*', user) and page *.book* .has_permission('view', user), and for book.has_permission('view', user) to itself check book.has_permission('*edit*', user). (Asterisks just for emphasis.)
I don't need anything as complex as django-rules, and I prefer the generic foreign key approach as I will not have large numbers and it keeps the model structure clean and focused. I'd like to avoid repeating the logic for these permission relationships in views, or cluttering models, and I'd ideally keep this permission structure centralized somewhere, ideally declaratively. For example
perm_hierarchy = {'view': ['edit', 'delete', ]}
model_perm_hierarchy = { Page : [Chapter, ],
Chapter : [Book, ]}
Then a layer that when checking for 'view' on Page checks for 'edit' and 'delete' permissions on that Page object.
And similarly when checking Page for a permission, checks Chapter for the same permission (if that same named permission is defined for Chapter).
Very happy to be told I'm thinking about this wrong.
I document a solution using django-rules on top of django-guardian in this answer
I'm currently designing a Django based site. For simplicity lets assume that it is a simple community site where users can log in and write messages to other users.
My current choice is wether to use the buildin User-Model or to build something my own. I don't need much from the buildin User: there will be no username (you e-mail address is you username), but you an set an internal Name of your choice which can be used by multiple users (like Facebook). Additionally, I don't need the permission system, since access to others will not be based on groups. So I would end up using only the email, firstname, lastname and password fields from the buildin User and everything else would be placed in a UserProfile.
On the other hand, the buildin User system will come handy on the backend of the site, since there is the chance I will need a group based permission system there.
All in all, it looks to me, that I rather build my one User Model and use the buildin only for access to the admin backend.
Is there anything wrong with my reflections?
Is there anything wrong with my reflections?
Yes.
My current choice is wether to use the buildin User-Model or to build something my own.
There is a third choice.
http://docs.djangoproject.com/en/1.2/topics/auth/#storing-additional-information-about-users
everything else would be placed in a UserProfile
Correct.
build my one User Model and use the buildin only for access to the admin backend
Don't build your own.
Do this:
If you'd like to store additional
information related to your users,
Django provides a method to specify a
site-specific related model -- termed
a "user profile" -- for this purpose.
As the author of django-primate I would like to add some comments. Django-primate which easily lets ju modify the built in User model is meant for just that. You might need just something a little extra, then use django-primate.
But there are problems, although I do not think modifying the django User model per se is a problem at all. One problem is that the "users" are quite different, the admin user and some other user are often not related. This can cause problems when for example an admin is logged in and then wants to login to the site as a "normal user", they do not expect those accounts to be related and do not expect to be logged in automatically as the admin user. This causes headaches for no reason. It also causes a lot of other headaches to implement the recommended related Profile model, you often need to make sure there is a contrib user for every profile and a profile for every contrib user if you for example want to use the authentication decorators. Forms and administration of "users" make this even more cumbersome. In short: usually something will go wrong in this process at some point, it's a curse.
I have mostly abandoned the contrib User model for anything else but for admins. Building another user model is really what you want, but you also want the authenicating part for that user, hence the common use of django contrib User (using it for the wrong reasons). The best solution if you are in a situation like this is to build your own authenication for that custom user model. This is actually quite easy and I cannot recommend this approach enough. I think that the official recommendation is wrong and that there should instead be good tools for authenticating custom user models built into django.
You might want to have a look at the recently created django-primate: https://github.com/aino/django-primate
I once built a custom user model, inheriting from the default one. It works, however, I wouldn't recommend it.
Currently, you have some requirements, but over time they may change. Django's user system is quite straightforward, and using it allows to adapt more easily to some of the most common use cases.
Another aspect to think about, is that there are several applications already available that you can use, and that may require Django's users. Using your own model, may make usage of such modules much more difficult.
On the other hand, hacking the Django's user system in order to comply with your current requirements may be tricky.
Moreover, migrating a 'Custom-User' to a 'Django-User' is always possible, so you are not really closing that door.
Overall, I think it really depends on what you mean with 'user'.
If you mean just a registration, and no real interaction with the core Django features, then I think a separate model is enough, especially because you can migrate at any time, with relatively little effort.
However, if for your application a 'user' maps to something very similar to the what Django is for, then I would use the Django User-Model.
I know that Django has a permission/group system. But that's mostly tied to each model. (Correct me if I'm wrong.)
My purpose is to have groups that can do multiple stuff. For example, one group can write to this and that. One group can edit this and that in different servers, different databases. Basically, it's beyond the model system.
I just want a custom groups system that's not tied to any model.
Three permissions are generated per model by default, but you can define additional permissions that you can use for other purposes. From there, the permissions decorator can handle authorization.
You need an app like django-guardian or something to handle object-level permissions, not model.
I will be creating an intranet site with multiple roles (client-employee, client-admin, staff team member). Each role will have a model that attaches (via One-to-One or ForeignKey field) to a user with custom fields. I want each role to have it's own set of permissions (like a group).
How can I store this permissions set inside my application. Groups seem to be defined as part of the contrib.admin app rather than in code. I couldn't find anything in documentation on how to define a group.
What is the best way to handle model level permissions. Maybe I could do a check in the model if see if the user has the right role-model.
Access control lists are tricky (some say dead), but Django comes with a good default implementation in contrib.auth equipped with:
Users
Permissions: Binary (yes/no) flags designating whether a user may perform a certain task.
Groups: A generic way of applying labels and permissions to more than one user.
A more detailed introduction can be found here:
http://parand.com/say/index.php/2010/02/19/django-using-the-permission-system/