afk
afk

Reputation: 558

password not geting hashed django rest framework

i'm using using customuser and trying to create user with drf but password not getting hashed. its returning raw password and because of that i can't use authentication its working with only user created by admin

class CustomUserMananager(BaseUserManager):
"""
Custom user model manager where email will be unique identifier

"""

def create_user(self, email, password, **extra_fields):
    """
    create and save user with given email and password
    """
    if not email:
        raise ValueError(_('email must be set'))
    email = self.normalize_email(email)
    user = self.model(email=email, **extra_fields)
    user.set_password(password)
    user.save()
    return user

def create_superuser(self, email, password, **extra_fields):
    """
    Create and save superuser with given email and password
    """
    extra_fields.setdefault('is_staff', True)
    extra_fields.setdefault('is_superuser', True)
    extra_fields.setdefault('is_active', True)

    if extra_fields.get('is_staff') is not True:
        raise ValueError(_('SuperUser must have is_staff=True'))
    if extra_fields.get('is_superuser') is not True:
        raise ValueError(_('SuperUser must have is_superuser=True'))
    return self.create_user(email, password, **extra_fields)

serializer:

class CustomUserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=False)

class Meta:
    model = CustomUser
    fields = ('id', 'first_name', 'last_name', 'email',
              'mobile_number', 'password', 'is_active', 'user_type', 'otp')

    def create(self, validated_data):
        return CustomUser.objects.create_user(**validated_data)

views:

    @api_view(["POST"])
@permission_classes((AllowAny,))
def register(request):
    #permission_classes = [(AllowAny, )]
    serializer = CustomUserSerializer(data=request.data)
    if serializer.is_valid():
        serializer.is_active = False
        user_otp = randint(999, 9999)
        otp_code = str(user_otp)
        email = request.data.get('email')
             send_mail(
            'Otp verification',
            otp_code,
            'jv',
            [email],
            fail_silently=False,
        )
        serializer.save(otp=user_otp)

        return Response({'response': 'User registered successfully, OTP sent to your Mail'}, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

settings.py:

from pathlib import Path
from django.urls import reverse_lazy
import os

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = 'f**w$%(m=pqt3=_r'


# Build paths inside the project like this: BASE_DIR / 'subdir'.


# SECRET_KEY = get_env_variable('SECRET_KEY')

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


# SECURITY WARNING: keep the secret key used in production secret!

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

ALLOWED_HOSTS = ['localhost']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.sites',
    'django.contrib.staticfiles',
    'phonenumber_field',
    'users',
    'api',
    'rest_framework',
    'rest_framework.authtoken',
    # 'allauth',
    # 'allauth.account',
    # 'allauth.socialaccount',


]

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 = 'carry.urls'

TEMPLATES_ROOT = os.path.join(BASE_DIR, "templates")

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [TEMPLATES_ROOT],
        '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 = 'carry.wsgi.application'


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

DATABASES = {
    # 'default': {
    #     'ENGINE': 'django.db.backends.sqlite3',
    #     'NAME': BASE_DIR / 'db.sqlite3',
    # }
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'carry',
        'USER': 'tboss',
        'PASSWORD': '5101',
        'HOST': 'localhost',
        'PORT': ''
    }
}

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'

    ),
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ]
}

# Password validation
# https://docs.djangoproject.com/en/3.1/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',
    },
]
LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True
STATIC_URL = '/static/'

AUTH_USER_MODEL = 'users.CustomUser'
SITE_ID = 1


EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'asdasd'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
AUTHENTICATION_BACKENDS = ('users.backends.EmailBackend',)

models.py:

 class CustomUser(AbstractBaseUser, PermissionsMixin):
    first_name = models.CharField(_('first name'), max_length=50)
    last_name = models.CharField(_("last name"), max_length=50)
    email = models.EmailField(_('email address'), unique=True)
    mobile_number = PhoneNumberField()
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now)
    user_type = models.IntegerField(_("user_type"))
    otp = models.CharField(_("otp"),max_length=10, default="0")

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserMananager()

    def __str__(self):
        return self.email

..................................................................................................

Upvotes: 0

Views: 432

Answers (1)

crazychukz
crazychukz

Reputation: 676

I see a couple of things that may cause this in the way you pass data to the create_user function. The function requires email, password, **extra_fields but you're passing just **validated_data I'm suprised that didn't cause any errors.

To run step by step investigation, let's ignore the manager for once and try adding a new user directly in the serializer directly.

class CustomUserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=False)


    class Meta:
        model = CustomUser
        fields = ('id', 'first_name', 'last_name', 'email',
                  'mobile_number', 'password', 'is_active', 'user_type', 'otp')
    
        def create(self, validated_data):
            # Since no required fields from your model, i will just use the email, first_name, last_name and password to create
            # for now. I am assuming you're pass them too
            email = validated_data.pop('email')
            first_name = validated_data.pop('first_name')
            last_name = validated_data.pop('last_name')
            password = validated_data.pop('password')
    
            new_user = CustomUser(
                email=email,
                first_name=first_name,
                last_name=last_name
            )
            new_user.is_active = True
            new_user.set_password(password)
            new_user.save()
    
            return new_user

If this was able a add a new user with hashed password then you say for sure that the problem is coming from the manager function.

Upvotes: 1

Related Questions