Adding permissions to django users which have add-on models - python

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/

Related

Django group permission activate

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 - custom file uploads based on criteria

I am currently struggling to find the best way to approach the following problem:
I have user registration implemented using django-registration and I want each user to be able to upload different set of documents. Each user will have an "agency", that require some extra documents, however those documents might be different.
So my User base class will have a one-to-one relation with all those base documents required for each user, however I am not sure how to let each agency define their own set of documents and how to tie it to the User.
Thanks.
Sounds to me like these are not one-to-one relations but one-to-many (specifically: one-User-to-many-Documents).
This would result in the Document containing a ForeignKey to the User.
In case one Document could be linked to many users, this may even be a many to many relationship.
In case, documents could be shared between User and Agency, either the Documents also have an optional ForeignKey to the Agency or - if no User needs to be linked to the document you might want to add a Generic Relationship "owner" to the Document that either links to a User or an Agency. See the Django documentation on Generic Relations for more detail.
However, Generic Relations are a little restricted, making it hard to use them in .filter() and .exclude() queries. Thus, I would recommend you to link to User and Agency in different attributes, if they do not have to share an attribute "owner" or "author", ...
Does each Agency only refer to one User or does an Agency "group" multiple Users? In these cases, refer to the Agency with a ForeignKey in the User model. This would mean, that you need to either inherit from the Django User Model or create a User Profile that contains your additionally defined variables. I personally prefer the second option here. See the amazing article on SimpleIsBetterThanComplex for these and other options on extending the User model, including great code examples.
If a User may also be part of multiple Agencies, you could instead use ManyToMany in the Agency and leave the User model alone. However, I would not recommend using this option if you do not intend to have multiple Agencies per user.
Update 1:
According to your comment, a User only belongs to one agency but an agency may link to multiple users. In this case, the user model should link to the Agency via ForeignKey. If an Admin User should assign Agencies, this is also easy to administrate, (at least in the Django admin), since the admin user then just has to edit the user itself (or the profile) in order to link the agency to it.
Using a post_save signal, you could check for a User that just has been saved, if the file type (type attribute (CharField with or without specific choices set) at the Document Model and Agency as well) required by the Agency is already linked to the User. If it is not, create and link it. The Document model should also contain the File-Field, so that it is easy to check, if the document has been uploaded already.
Update 2:
Just to help you with this, here is another great article from SimpleIsBetterThanComplex about Django signals.

Model design for a user who can have roles at multiple organizations

I need a Django model where a User can have a Function with any number of Organisations. His permissions (change, view, delete) with the organization are determined by his Role. I am pretty sure I only need an "admin" and a "member" role.
This would require row-level permissions, so I decided to go with django-guardian. I am having trouble choosing the proper model design. These are the alternatives
The first one would have the advantage of creating new roles, but I don't think I need that. Also I can enforce unique_together so that a User can only have 1 function at every company. Would I set the can_change permission at the Role and infer the row level permission based on the relation between User and Organization? The would mean I do not even need django-guardian, right?
The second one looks much simpler, but maybe that is deceptive. The permissions would have to be set as soon as a User is added to an Organization and are definitely row-level.
What is the right strategy here?
To clarify: in both cases a user can be an admin of one organization and simply a member of another organization.
Use the Party Model.
A user is not a person, it's a user. Person and organization are parties. A party hasOne (or no) user.
A person hasMany (many2many) relationships with an organization:
Individual -< Relationship >- Organization
Organizations can have relationships with each other too.

Django: multiple accounts, with multiple users under each account, but account-specific data

Using Django 1.5 here. I have an application I've created that currently has one big set of data, for one "account" if you will. Meaning all the data in all the models in my application are available to all logged-in users. Now, I want to be able to allow more people to use my application but with their own set of data. So I need to separate users into different accounts with different sets of data for each account. There could potentially be one or multiple users that has access to each account. At this time I don't need different users within one account to have different levels of access though I do intend for one user to be the account "owner".
I know that to make this conversion, I of course need to add a field to every model with a foreign key to a new "account" model. But beyond that I'm a little foggy. This appears to be a square peg in the round hole of Django's auth system. So the question is, what is the best approach?
A few thoughts I had so far:
Simply filter each and every query by account
Wrap each and every view with a decorator, but with multiple models, do I have to create a different decorator for each model? Can I tell from within the decorator which model is being accessed?
Somehow make use of the Auth system's user_passes_test decorator, but again, different models.
Extend the auth system to include a request.account attribute
Create a new mixin for my views? What if I'm not using exclusively CBVs?
Different middleware?
I considered using a new group for each account and then filtering by group instead of a new account model but I predict that would be a poor fit in this situation, as it isn't using groups as they were intended.
This is less of a code question and more of a big-picture, best-practices question. How would you approach this?
What you request is not so exotic: This is called authority data - you seperate your users to authorities and each authority will have each own data. For instance, you may have a number of departments in an organization - the data of each department can be edited only by members of the same department. I have already written a blog post with a simple approach to that using django:
http://spapas.github.io/2013/11/05/django-authoritiy-data/
To recap the post, I propose just adding an Authority model for which your User will have a ForeignKey (each User will have a Profile).
Now, all your Models whose data will belong to specific Authorities will just contain a ForeignKey to Authority. To check for the permissions you could use CBVs - the django admin will only be available to the central Administrators that have access to all the data. I recommend against using the django permissions for authorization of Authority data. If you want read the post which is much more detailed and ask here any questions.

Is there a Django app that can handle groups and permissions?

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.

Categories