Search code examples
pythondjangodjango-modelsdjango-rest-frameworkdjango-serializer

django-rest-framework custom user model login failed


I am using django custom usermodel with restframework , after registering successfully I am unable to login for normal users.I am able to login via the initial superuser but if I create new superuser ,they are registered successfully but gives error while logging in as when trying with a normal user.

Error

Please enter the correct email and password for a staff account. Note that both fields may be case-sensitive.

For few profiles I also observed following error in admin panel.

invalid password format or unknown hashing algorithm 

models.py

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
from django.utils import timezone


class UserManager(BaseUserManager):

    def _create_user(self, email, password, is_staff, is_superuser, **extra_fields):
        if not email:
            raise ValueError('Users must have an email address')
        now = timezone.now()
        email = self.normalize_email(email)
        user = self.model(
            email=email,
            is_staff=is_staff,
            is_active=True,
            is_superuser=is_superuser,
            last_login=now,
            date_time_onboarded=now,
            **extra_fields

        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password, **extra_fields):
        return self._create_user(email, password, True, True, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        user = self._create_user(email, password, True, True, **extra_fields)
        return user


class AppOnboarding(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=254, unique=True)
    product_name = models.CharField(max_length=254, null=True, blank=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=True)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_time_onboarded = models.DateTimeField(auto_now_add=True)

    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def get_absolute_url(self):
        return "/users/%i/" % (self.pk)

serializers.py

from rest_framework import serializers

from .models import AppOnboarding


class AppOnboardingSerializer(serializers.ModelSerializer):
    class Meta:
        model = AppOnboarding
        fields = ['email', 'product_name', 'password']
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        app_onboard = AppOnboarding(
            email=self.validated_data['email'],
            product_name=self.validated_data['product_name']
        )
        password = self.validated_data['password']

        app_onboard.set_password(password)
        app_onboard.save()

    def save(self):
        app_onboard = AppOnboarding(
            email=self.validated_data['email'],
            product_name=self.validated_data['product_name']
        )
        password = self.validated_data['password']

        app_onboard.set_password(password)
        app_onboard.save()

urls.py


from django.urls import path
from rest_framework import routers
from . import views



router = routers.DefaultRouter()
router.register('app', views.AppOnboardingView)
urlpatterns = router.urls

views.py

from django.shortcuts import render

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status, viewsets

from .serializers import AppOnboardingSerializer
from .models import AppOnboarding




class AppOnboardingView(viewsets.ModelViewSet):
    queryset = AppOnboarding.objects.all()
    serializer_class = AppOnboardingSerializer

*settings.py

"""
Django settings for nrn project.

Generated by 'django-admin startproject' using Django 2.2.5.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

# , EMAIL_HOST_USER   , EMAIL_HOST_PASSWORD
from .email_info import EMAIL_HOST, EMAIL_PORT
import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'mz)6t6hfo*44sz*g)u&2o5!9p9azk!lwuju=*0lp_-c5)m-hj4'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'send',
    'apponboarding'
]

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.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'nrn.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'nrn.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'


EMAIL_HOST = EMAIL_HOST

EMAIL_PORT = EMAIL_PORT


EMAIL_USE_TLS = False

EMAIL_USE_SSL = False

AUTH_USER_MODEL = 'apponboarding.AppOnboarding'

# REST_FRAMEWORK = {
#     'DEFAULT_AUTHENTICATION_CLASSES': [
#         'rest_framework.authentication.SessionAuthentication',
#     ],
# }

# AUTHENTICATION_BACKENDS = (
#     'django.contrib.auth.backends.RemoteUserBackend',
#     'django.contrib.auth.backends.ModelBackend',
# )
  • Tried all the solutions on stackoverflow for similar problem but still it not working.
  • Any help is highly apppreciated.

Solution

  • In your settings you have to mention your custom auth user model if you defined a custom user.

    AUTH_USER_MODEL = 'your_custom_account.User'
    

    For permissions you can add the following code to AppOnboarding

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True
    
    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True
    
    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin