Search code examples
python-3.xdjangodjango-formsdjango-usersdjango-3.1

Why django is accepting two diiferent passwords? Giving no error at all


Why this code is accepting both password and confirm_password field? without errors Here is first models.py file: (indent is not a problem here)

from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from .managers import UserManager
from django.utils.translation import ugettext_lazy as _

# Create your models here.
ROLES = (
    ('Customer', 'Customer'), ('Vendor', 'Vendor')
)
class User(AbstractBaseUser):
    email = models.EmailField(verbose_name='Email Address', max_length=255, unique=True)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False)
    admin = models.BooleanField(default=False)
    role = models.CharField(max_length=15, choices=ROLES)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']

objects = UserManager()

def __str__(self):
    return self.email

def get_name(self):
    return self.first_name + ' ' + self.last_name

def get_role(self):
    return self.role

def has_perm(self, perm, obj=None):
    return True

def has_module_perms(self,  app_label):
    return True

@property
def is_staff(self):
    return self.staff

@property
def is_admin(self):
    return self.admin

@property
def is_active(self):
    return self.active

Next the manager for user model: Here I'm just accepting data and creating accounts only.

from django.contrib.auth.models import BaseUserManager
from django.db import models
from django.utils.translation import ugettext_lazy as _

class UserManager(BaseUserManager):

use_in_migrations = True

def _create_user(self, email, password, **extra_fields):
    if not email:
        raise ValueError('User must have an Email Address')
    user = self.model(email=self.normalize_email(email), **extra_fields)
    user.set_password(password)
    user.save(using=self._db)
    return user

def create_user(self, email, password, **extra_fields):
    extra_fields.setdefault('staff', False)
    extra_fields.setdefault('admin', False)
    return self._create_user(email, password, **extra_fields)

def create_superuser(self, email, password, **extra_fields):
    extra_fields.setdefault('staff', True)
    extra_fields.setdefault('admin', True)

    if extra_fields.get('staff') is not True:
        raise ValueError('Superuser must have "staff" = True')
    if extra_fields.get('admin') is not True:
        raise ValueError('Superuser must have "admin" = True')
    return self._create_user(email, password, **extra_fields)

In here, I want create model forms for creating user accounts Here is forms.py file:

from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import User

class RegistrationForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)
    password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('email', 'first_name', 'last_name', 'role', 'password', 'password2')

    def clean_email(self):
        email = self.cleaned_data.get('email')
        qs = User.objects.filter(email=email)
        if qs.exists():
            raise forms.ValidationError('Email is already taken, try another email')
        return email

    def clean_password2(self):
        password = self.cleaned_data.get('password')
        password2 = self.cleaned_data.get('password2')

        if password and password2 and  password != password2:
            raise forms.ValidationError('Passwords did not match, try again')
        return password

class UserAdminCreationForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)
    password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)

    def clean_password2(self):
        password = self.cleaned_data.get('password')
        password2 = self.cleaned_data.get('password2')
        if password and password2 and password != password2:
            raise forms.ValidationError('Passwords did not match, try again')
        return password

    def save(self, commit=True):
        user = super(UserAdminCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data['password'])
        if commit:
            user.save()
        return user


class UserAdminChangeForm(forms.ModelForm):
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = User
        fields = ('email', 'first_name', 'last_name', 'role', 'password', 'admin', 'staff')

    def clean_password(self):
        return self.initial['password']

Lastly here is the views file:

from django.shortcuts import render, redirect
from .models import User
from .forms import RegistrationForm
from django.contrib import messages
from .models import User
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
import logging

logger = logging.getLogger(__name__)

# Create your views here.
def register(request):
    form = RegistrationForm()

    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            email = form.cleaned_data['email']
            first_name = form.cleaned_data['first_name']
            last_name = form.cleaned_data['last_name']
            password = form.cleaned_data['password']
            role = form.cleaned_data['role']
            user = User.objects.create_user(
                email=email,
                password=password,
                first_name=first_name,
                last_name=last_name,
                role=role,
            )
            logger.info('New account created by {0} {1} with email:{2} as {3}'.format(
                first_name, last_name, email, role
            ))
            messages.success(request, 'Hi, ' + first_name + ', your account is created successfully!')
            return redirect('/')
    context = {'form': form,}
    return render(request, 'user/register.html', context)

def user_login(request):
    if request.method == 'POST':
        email = request.POST.get('email')
        password = request.POST.get('password')
        user = authenticate(request, email=email, password=password)
        if user is not None:
            login(request, user)
            return redirect('user:home')
        else:
            messages.warning(request, 'Email or Password is incorrect, try again')
    context = {}
    return render(request, 'user/login.html', context)

def user_logout(request):
    logout(request)
    return redirect('user:login')

@login_required(login_url='user:login')
def home(request):
    users = User.objects.all()
    context = {'users': users}
    return render(request, 'user/home.html', context)

Solution

  • I can not see a password2 field in your registration form. Most probably there is no password2 and according to your code written, "passwords are equal or not" condition will be checked if both passwords are provided. As password2 does not exist, the following "if condition" is always false. Hence validation error is not raised and the password is returned every time.

    if password and password2 and password != password2:
                raise forms.ValidationError('Passwords did not match, try again')
    return password