Custom system for permissions with django - python

I'm looking for a way to make my own system of groups and permissions in Django. I know that Django by default brings a system of groups and permits, but in my project due to teacher requirements I had to create my own models.
You can create new groups and add permissions to those groups, but since they are not the default models of django I cannot use the template-level functions such as 'perms.car.add_car' for example. What I mean by this? That at the template level, I don't know how to validate if the user has the permission. I hope I have explained myself well, I await your answers and thank you in advance!

You should be able to access the current user's attributes from templates with {{user.some_attribute}}.
You can extend the default django.contrib.auth.models.User class with a one-to-one relationship with a CustomUser class you create, and access it from template the way described above, meaning:
{{ user.one_to_one_custom_user_field.some_attribute }}
For more info about extending User look at the docs.
In this CustomUser class add as you see fit:
functions for interacting with the user group classes you created and verifying whether current user is in them or not, or has the right permissions
flag variables (or any other indicative attribute) to indicate the user's groups and permissions.
Use one of these options as the some_attribute accessible from template.

Related

In Django , How to handle multi user types with more than 1 user has access to same content?

In a Django Application, I have a model called application.py which is created by a user say "u". I want to list all the application created by the user "u" later, so i may need to add a reference to the model application.py from user.py.
I have one more requirement , as an admin , i need to provide access to any number of users to the same applications. So I assume this can be done with many to many relation.(Since users can access many applications).
Now the question is , is it possible to implement this behavior with user groups ,with one group is responsible for handling one application, so that in a later point of time i can add as many users as needed from the backend to respective groups to manage the same application.?
Which one is better , managing the users using many to many relation with model application.py or relating a group to application.py
and managing users using groups.
There are multiple ways to solve this, but it from a future flexibility point of view this sounds like a Role, Permission and Group relationship:
Applications have a many-to-many relationship to Users through a Membership.
Each membership would point to a Role. That could be hard-coded to start with (just a string like 'admin' or 'viewer').
This way a User can be associated to an Application as viewer or as an admin.
In the future, to add flexibility, you would have a model Role that describes the role (and could be associated to one or more Permission models to list the permissions for each role). So Membership would have a pointer to Role via a ForeignKey.
Check the documentation on extra fields on a many-to-many relationship.
There are also packages that solve this problem, e.g. django-permissions and django-role-permission

Extend User Model or Custom Pipeline in Social-App-Django

I am implementing social-app-django (not the deprecated one; the one that relies on Python-social-auth) with django 1.11 (not using Mongo). My application will need to store and manipulate a lot of data on users other than that which is fetched from their social media accounts at login.
I don't need to fetch or collect any extra data when the user authenticates, but various actions they perform on my site will need to be saved to their user model. I am wondering which of the following approaches is preferred (I've searched extensively online, but can't find a specific explanation of why to use one vs the other):
Create my own user model in my app's models.py (call it MyUser) that doesn't extend anything special, and then add a function in the authentication pipeline that associates the social-app-django user with a corresponding instance of MyUser. Leave AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL unchanged.
or...
Create my own user model in my app's models.py, and in the project's settings.py set AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL to point to MyUser. Leave the pipeline unchanged. In this case, I was wondering whether someone could clarify what MyUser and its manager should extend, and what I need to import in modules.py (I am confused because a lot of stack overflow posts are referring to deprecated versions of this module and I keep getting errors). Also, in this case should I be setting both AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL, or just one of them?
Do these two methods essentially achieve the same thing? Is one more reliable/preferred for some reason? Or, should I be doing both? Thanks very much for any assistance.
Another detail: I would like to be able to access the User database not only from the app I am currently building, but also from other apps (within the same Django project) that I will build in the future. Does this affect anything?
Since I see this has a decent number of views I will post the solution I eventually came to.
Both django and social-app-django (or any other social auth module) make use of the default User model for authentication. While it's possible to edit this model to add custom parameters, I don't recommend it. It's not good abstraction or modularization. If you make a mistake when configuring the model, you won't just break a specific feature on your site, but you might also break the authentication itself.
The only circumstances I can think of under which you'd want to edit the default user model itself is if you need to make changes that affect the authentication flow itself (for example, adding your own custom authentication provider).
It's much easier and safer to create a new model called UserProfile, with a required one-to-one relationship to a User object. Now, you can treat the User object as the authentication part, and the UserProfile object as the content/storage part. You won't have to mess with the User model very often, and the UserProfile model doesn't matter for authentication purposes. Note that in this configuration you should NOT need to change the AUTH_USER_MODEL or SOCIAL_AUTH_USER_MODEL fields in the settings.py file.
If you take this approach, you will need to add a custom step in the authentication pipeline in which you create a new UserProfile object and associate it with the User who is currently logging in.

Can I link Django permissions to a model class instead of User instances?

I know how permissions/groups/user work together in a "normal" way.
However, I feel incomfortable with this way to do in my case, let me explain why.
In my Django models, all my users are extended with models like "Landlord" or "Tenant".
Every landlord will have the same permissions, every tenant will have other same permissions.. So it seems to me there is not interest to handle permission in a "user per user" way.
What I'd like to do is link the my Tenant and Landlord models (not the instances) to lists of permissions (or groups).
Is there a way to do this? Am I missing something in my modelisation? How would you do that?
django.contrib.auth has groups and group permissions, so all you have to do is to define landlords and tenants groups with the appropriate permissions then on your models's save() method (or using signals or else) add your Landlord and Tenant instances to their respective groups.

Django best user model design

Probably some of you would tell that is a recurrent topic, but after reading many articles, it still seems very ambiguous to me. My question is about the best way to use and to extend the User model preserving the authentication (and others) mechanisms available in Django. However, I prefer to describe my design:
There are users (Patients) that can sign up providing basic info (first name, last name, birth date, gender, email, password). Preferably, email should replace the username.
When a Patient is in the application, it can register a new Patient (imagine a member of the family), but email and password are not required because they won't log into the system.
For the first part, Django doc propose to extend User with a OneToOne relation to a Profile. However, to replace username by email they propose then to create a custom User extending from an AbstractUser, as well as an associated UserManager. The second requirement is like doing a one-to-many relation from users to users. So, according to Django, which should be the best strategy: creating a completely new user model and the one-to-many user-user adding an specific attribute that distinguish between main users and family members? OR extending Django User with a Profile and then a one-to-many relation profile-profile? Which option preserves the best the benefits of Django user authentication and model administration?
Thank you for any comment, suggestion, example.
First, if you want to use email as username, use the Django custom user functionnality. It works well.
Then, note that it's not because you created your own User that you can't extend it with a Profile.
So, a good solution could be :
Create a Django custom User without trying to add specific fields to it (the one and only purpose here is to use email to log instead of username).
Create a PatientProfile class that have a one-to-one relatioship (blank=True) with User class.
This way, a patient that can log in will be related to a User instance and will use this instance for this purpose. On the other hand, the patient who can't log in won't be related to any User instance.
In the end, there's no problem to use OneToMany relationship with PatientProfile for what's you want to do.

django user and custom user class

In Django you have some naturally defined User class. My app also has a User class defined (they dont conflict, that's not the question)
My question is, since these two User classes conceptually represent the same thing (well, users) then it would be natural to integrate them. That is, have a single User class that contains all methods and variables of both classes.
What is the best way to achieve this?
There are (at least) two possibilities:
1) Use the 'custom user' functionality of Django (since Django 1.5), or
2) Use a OneToOneField to the django.contrib.auth User from your own user class.
The first allows you to customize more, but you might get some problems if you try to use third-party-apps that are either not ready for custom users or need specific properties of the stock User. For example, Django Guardian doesn't work if you remove the User-Group relationship.
The second is less intrusive, but doesn't allow you to customize the existing fields of User. Also, you need to manually create the instance of your own user class at registration time.
You should read the documentation about Extending the existing User model.
If you wish to store information related to User, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user. For example you might create an Employee (note: called MyUser below) model:
from django.contrib.auth.models import User
class MyUser(models.Model):
user = models.OneToOneField(User)
newfield1 = models.CharField(...)
AUTH_USER_MODEL = 'myapp.MyUser'

Categories

Resources