I have a django project, where i have custom user model stated as below :
class CustomUserModel(AbstractUser):
# MAKING email field mandatory
email = models.EmailField(unique=True)
# KEEP TRACK OF USER'S PASSWORD CREATION DATE TO ENFORCE 3MONTH MAX VALIDITY
password_created_date = models.DateTimeField(default=timezone.now, null=False, blank=False)
# WHICH DEPARTMENT IS USER MEMBER OF
department = models.ForeignKey(Department, on_delete=models.PROTECT, default=1, null=False, blank=False)
# WHICH TEAM IS USER MEMBER OF
team = models.ForeignKey(Team, on_delete=models.PROTECT, default=1, null=False, blank=False)
# USER TYPE - DETERMINES SOME ATTRIBUTES FOR USER - I.E. MAX AMOUNT OF ACTIVITY
user_type = models.ForeignKey(UserType, on_delete=models.PROTECT, default=1, null=False,blank=False)
# FIRST NAME - REQUIRED FIELD
first_name = models.CharField(max_length=30, blank=False, null=False)
# LAST NAME - REQUIRED FIELD
last_name = models.CharField(max_length=30, blank=False, null=False)
# OVERRIDE DEFAULT SAVE METHOD FOR USER THAT EMAIL IS REQUIRED ELSE - ValueError
def save(self, *args, **kwargs):
if not self.email:
raise ValueError("Email field is required")
super().save(*args, **kwargs)
# OVERRIDE DEFAULT SAVE PASSWORD METHOD SO THAT DATE OF CREATION IS ALSO CREATED
def set_password(self, raw_password):
super().set_password(raw_password)
self.password_created_date = timezone.now()
self.save()
In my settings.py i have included AUTH_USER_MODEL = 'attendance.CustomUserModel'
here is error flow:
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/account/login/
Django Version: 4.1.7
Python Version: 3.9.4
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'attendance',
'services',
'django_otp',
'django_otp.plugins.otp_static',
'django_otp.plugins.otp_totp',
'django_otp.plugins.otp_email',
'otp_yubikey',
'two_factor',
'two_factor.plugins.phonenumber',
'two_factor.plugins.email',
'two_factor.plugins.yubikey']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django_otp.middleware.OTPMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File " PycharmProjects\IOAS_Project\venv\lib\site-packages\django\contrib\auth\backends.py", line 46, in authenticate
user = UserModel._default_manager.get_by_natural_key(username)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\contrib\auth\base_user.py", line 46, in get_by_natural_key
return self.get(**{self.model.USERNAME_FIELD: username})
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\db\models\query.py", line 650, in get
raise self.model.DoesNotExist(
During handling of the above exception (CustomUserModel matching query does not exist.), another exception occurred:
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\core\handlers\exception.py", line 56, in inner
response = get_response(request)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\views\generic\base.py", line 103, in view
return self.dispatch(request, *args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\utils\decorators.py", line 46, in _wrapper
return bound_method(*args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\views\decorators\debug.py", line 92, in sensitive_post_parameters_wrapper
return view(request, *args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\utils\decorators.py", line 46, in _wrapper
return bound_method(*args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\utils\decorators.py", line 134, in _wrapped_view
response = view_func(request, *args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\utils\decorators.py", line 46, in _wrapper
return bound_method(*args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\views\decorators\cache.py", line 62, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\two_factor\views\core.py", line 417, in dispatch
return super().dispatch(request, *args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\formtools\wizard\views.py", line 244, in dispatch
response = super().dispatch(request, *args, **kwargs)
File "C:\Users\janeg\PycharmProjects\IOAS_Project\venv\lib\site-packages\django\views\generic\base.py", line 142, in dispatch
return handler(request, *args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\two_factor\views\core.py", line 140, in post
response = super().post(*args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\two_factor\views\utils.py", line 169, in post
return super().post(*args, **kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\formtools\wizard\views.py", line 294, in post
if form.is_valid():
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\forms\forms.py", line 205, in is_valid
return self.is_bound and not self.errors
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\forms\forms.py", line 200, in errors
self.full_clean()
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\forms\forms.py", line 438, in full_clean
self._clean_form()
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\forms\forms.py", line 459, in _clean_form
cleaned_data = self.clean()
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\contrib\auth\forms.py", line 217, in clean
self.user_cache = authenticate(
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\views\decorators\debug.py", line 42, in sensitive_variables_wrapper
return func(*func_args, **func_kwargs)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\contrib\auth\__init__.py", line 77, in authenticate
user = backend.authenticate(request, **credentials)
File " \PycharmProjects\IOAS_Project\venv\lib\site-packages\django\contrib\auth\backends.py", line 50, in authenticate
UserModel().set_password(password)
File "C:\Users\janeg\PycharmProjects\IOAS_Project\attendance\models.py", line 61, in set_password
self.save()
File " \PycharmProjects\IOAS_Project\attendance\models.py", line 53, in save
raise ValueError("Email field is required")
Exception Type: ValueError at /account/login/
Exception Value: Email field is required
I've implemented Django two factor auth https://github.com/jazzband/django-two-factor-auth/ into project to provide 2FA for users.
it works - users can set up 2FA, authenticate with it, log in even without 2FA if they didn't allowed it. ** Strange things happens if they try to login with invalid credentials :**
- If username is correct and password incorrect - page reloads with no error message (as there is normally when two factor auth is used in project without custom user model
- If username is INCORRECT and password whatever you type in - it returns error - that is cause by condition for creating a new user (see my user model) - this is the problem - if credentials are not valid it should return error message and not to try to create new user if username is not in database.