Storing password in multiple entities - Django - python

I'm working on Django project and I want to have two different entities in database - (default Django) User and Doctors. I want to have stored password in both entities.
def post(self, request, pk):
username = Doctor.objects.get(pk=a).email
password = Doctor.objects.get(pk=a).password
user = User.objects.create_user(username, username, password)
user.save()
return redirect('ps:index')
Atribute in forms.py for DoctorForm:
password = forms.CharField(widget=forms.PasswordInput)
But this is not working for passwords. I assume that the reason is hashing and salt. How to solve it?
Any help would be appreciated.

The password stored in database is hashed. If you want to save a new password, use user.set_password(new_password) and user.save(). Then copy the user.password to another entity.

Related

How to change the field name of Serialzed User Model on frontend in Django Rest Framework?

I am making a simple Login/Logout App using REST API in Django DRF. I am using the default User model for this behavior.
In the Login API, I wanted to authenticate the user with email, hence I wrote the custom authentication using ModelBackend. Everything works fine.
But, I want to change the word username to email in the front of the Login API. I tried using the source attribute, but it does not change. Is there any easy way to do it? I am looking for something like verbose_name, that is used in Django Models.
My serializers.py is:
class LoginSerializer(serializers.Serializer):
username = serializers.CharField(source='Email')
password = serializers.CharField()
def validate(self, data):
user = authenticate(**data)
if user and user.is_active:
return user
raise serializers.ValidationError('Incorrect Credentials Passed.')
Again, I am using the default User Model, and I don't want to overwrite/override/extend the User Model. I just want to change the name of the field username on the frontend to be shown as email.
You need to pass a value called email and not username to your ModelBackend subclass:
class LoginSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
def validate(self, data):
user = authenticate(**{'email': data['username'], 'password': data['password']})
if user and user.is_active:
return user
raise serializers.ValidationError('Incorrect Credentials Passed.')

Storing passwords in MySQL database in hashed form Django App

I am working on a Django app and my django is using MySQL database which can be handled through django admin page (inbuilt).
Currently, I m creating users who can access the app by manually creating username and password in Django administration --> Authentication and Authorization --> users --> add. (that's what i want and hence my requirement is satidfied here.)
When i create user and add password through django admin, it gets hashed and no one can see the password in plain text.
Also, my django app consists of login through which user can authenticate and also it consists of model (Login) which records who has logged-in. But the problem here is that, when the user Logs-In the Login model stores the password in Plain text in Db (MySQL) and i want that the Login model should store the password in hashed form.
Note:- i have included ALL the hashers in settings.py
here's the code
Models.py
from django.db import models
from datetime import datetime
from django.contrib.auth.models import User
# Create your models here.
class LoginEvent(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date_and_time = models.DateField(auto_now_add=True)
def __str__(self):
return str(self.user) + ': ' + str(self.date)
class Login(models.Model): #model that stores username and Password in MySQL database in plain text.
username = models.CharField(max_length=50)
password = models.CharField(max_length=32, default="", null=False)
def __str__(self):
return self.username
Views.py
from .models import Login
from datetime import datetime
# Create your views here.
def login_view(request):
context = {}
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
authform_data = authForm (request.POST or None)
user = authenticate(request, username=username, password=password)
if user:
login(request, user)
authform_data.save()
return HttpResponseRedirect(reverse('IP form'))
else:
messages.error(request,'Please provide valid credentials')
return render (request,"first_app/login.html", context)
else:
return render (request,"first_app/login.html", context)
Settings.py
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
]
thnx for the help. :-)
I figured it out.! Using django's Inbuilt User model as said by #Daniel Roseman, no upon login the user password gets Hashed. thx all for replying. :-)

Adding a new field along with username and password in django's login form

I want to edit the login form provided by django and don't want to build a new one because of the security issues. I have looked at other solutions like How to use another field for logging in with Django Allauth? it's a good example but it assigns email id based on mobile number. However I want to add another field that isn't particularly to authenticate just for input based on which redirection is done. I am quite confused about my approach and whether or not it is possible to do so. Kindly suggest. Thanks.
You can do that in your forms.py file by doing this.
class UserLoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Username'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Password'}))
yourfield = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control','placeholder':'yourfield'}))
def clean(self, *args, **kwargs):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
#user_qs = User.objects.filter(username=username)
#if user_qs.count() == 1:
# user = user_qs.first()
if username and password:
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError("This user does not exist")
if not user.check_password(password):
raise forms.ValidationError("Incorrect password")
if not user.is_active:
raise forms.ValidationError("This user is no longer active")
return super(UserLoginForm, self).clean(*args, **kwargs)
Apologies if I've misunderstood your question, but here is how I've added extra fields to user registration it which seems pretty straightforward. I've included some extra related methods just to be verbose:
../forms.py:
class CustomRegistrationForm(RegistrationForm):
"""
Form for registering a new user account.
Subclasses should feel free to add any additional validation they
need, but should avoid defining a ``save()`` method -- the actual
saving of collected user data is delegated to the active
registration backend.
"""
username = forms.RegexField(regex=r'^[\w.#+-]+$',
max_length=30,
label="Username",
error_messages={'invalid': "This value may contain only letters, numbers and #/./+/-/_ characters."})
email = forms.EmailField(label="E-mail")
password1 = forms.CharField(widget=forms.PasswordInput,
label="Password")
password2 = forms.CharField(widget=forms.PasswordInput,
label="Password (again)")
extra_field = forms.CharField([field options])
def clean(self):
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:
if self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("The two password fields didn't match.")
return self.cleaned_data
Then, simply set your register URL to use the proper form class:
../urls.py:
url(r'^accounts/register/$', RegistrationView.as_view(form_class=accounts.forms.CustomRegistrationForm), name='registration_register'),
Is this field not part of your standard model, or does your input need to do some extra work? You can set a signal to make some extra magic happen when the user is registered:
from forms import CustomRegistrationForm
def user_created(sender, user, request, **kwargs):
form = CustomRegistrationForm(request.POST)
user_account = get_user_account(user)
user_account.persona = form.data['persona_tier']
user_account.save()
from registration.signals import user_registered
user_registered.connect(user_created)
FYI I'm using django-registration-redux backend but this approach should help get you close regardless.

Django non persistent model field

I have a Django Model where I create an random password for the user.
Manager.py:
class UserManager(BaseUserManager):
def create_user(self, password=None):
user = self.model()
if password:
user.set_password(password)
else:
user.set_password(user.generate_password())
user.save()
return user
I then want to send out an email to the user with their temporary password after the model is saved.
#receiver(post_save, sender=User)
def registration_email(sender, instance, created, **kwargs):
if created:
pass
My problem is that the password is hashed (which is good) so I cannot do the following in the post_save function... instance.password. So is there a way I can have a non persistent model field to read from (just on this first save) i.e. instance.tempcleartext. Or is there a better way?
To answer your question as-is, you can grab a reference to the password before you set it:
self.temp_pw = user.generate_password()
user.set_password(self.temp_pw)
And then you have access to the password as self.temp_pw but it will be a volatile property, not one that gets saved to the db.
HOWEVER, I would strongly recommend against doing this and particularly against sending passwords by email. It is far better to provide a password reset feature, IMO.

How to have django auth take username and firstname same value?

Django auth has username and first_name fields. But username has field option unique=True. This prevents a user from giving first_name same as username when registering and raises IntegrityError. How to bypass this and also keeping username unique? ie. no two users should have the same username. But username can be same as first_name. And two users can have same first_name, last_name.
You cannot achieve that. If you want to have the same value in fields first_name and username and one of them is not unique, the other one also cannot be unique.
As far as I understand what you're doing here, you just want to display first_name instead of username - to achieve that just use {{ user.first_name }} instead of just {{ user }}. If you need to store some additional information about users you can also define Profiles where you can implement your own __str__ method.
You will have to implement custom authentication backend that used first_name as username.
During registration, you can duplicate username with first_name or generate random username which you will never use, as you will always use first_name instead.
You will have have to take care of
Take create while creating/registering user.
Username (in your case first name) should be unique
The code in authentication backend would be something like (this is just a sample code):
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(first_name=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
Refer Writing authentication backend.
There are quite a few examples of how to user email to authenticate that you can refer to authenticate using first_name.

Categories