user13594086
user13594086

Reputation:

django how to create hashed password using create_user() method

I have this problem for a month.

I'm using abstractbasemodel and basemanagerto to create a login and signup API using rest framework.

However, when I create a user password, it is saved as raw data since I use set_password() method and custom model manager confuses me...

This is my code :

class UserProfileSerializer(serializers.ModelSerializer):    
    class Meta:
        model        = UserProfile
        fields       = ('id' ,'email' ,'name' ,'password')
        extra_kwargs = {
            'password':{
                'write_only':'True',
                'style': {'input_type': 'password'}
            }
        } 

        def create(self, validated_data):
            user = UserProfile.people.create_user(
                email = validated_data['email'],
                name  = validated_data['name'],
                password = validated_data['password']
            )

class UserProfileViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.UserProfileSerializer
    queryset = models.UserProfile.people.all()
    authentication_classes = (TokenAuthentication, )
    permission_classes     = (UpdateOwnProfile, )
    filter_backends        = (SearchFilter, )
    search_fields          = ('name', 'email')


class UserLoginApiView(ObtainAuthToken):
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES

class UserProfileManager(BaseUserManager):
    def create_user(self, email, name, password=None):
        print("user model manager")
        if not email:
            raise ValueError('User Must Have an Email Address')
        email = self.normalize_email(email)
        user = self.model(email=email, name=name )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, name, password):
        user = self.create_user(email, name, password)
        user.is_superuser = True
        user.is_staff     = True
        user.save(using=self._db)
        return user

class UserProfile(AbstractBaseUser,PermissionsMixin):
    email           =         models.EmailField(max_length=255,unique=True)
    name            = models.CharField(max_length=255)
    is_active       = models.BooleanField(default=True)
    is_staff        = models.BooleanField(default=False)

    people = UserProfileManager()

    USERNAME_FIELD  = 'email'
    REQUIRED_FIELDS = ['name']

    def get_full_name(self):
        return self.name

    def get_short_name(self):
        return self.name

    def __str__(self):
        return self.email

class Profile(models.Model):
    user         =     models.OneToOneField(UserProfile,on_delete=models.CASCADE,relat    ed_name="Profile")
    location     =     models.CharField(max_length=100,blank=True,null=True)
    bio          =     models.CharField(max_length=100,blank=True,null=True)
    creationDate = models.DateTimeField(auto_now_add=True)
    follower     =     models.ManyToManyField(UserProfile,related_name="Following",blank=True)

    class Meta:
        verbose_name='Profile'
        verbose_name_plural='Profiles'

I also defined auth user model in settings :

AUTH_USER_MODEL='profiles.UserProfile'

to make sure Django uses my custom user model.

I don't know whats wrong as there is no error and only superusers that are created in terminal using manage.py are saved with hashed password.

Users which are created with my viewsets are saved with raw password.

First, I named the model manager "objects" and now, its people but the create user method wont run at all.

Upvotes: 0

Views: 978

Answers (1)

Md. Tanvir Raihan
Md. Tanvir Raihan

Reputation: 4285

You can use django's built in hasher to create hashed password. It can be applied in .create method. First import from django.contrib.auth.hashers import make_password and then modify .create() method,

    def create(self, validated_data):
        user = UserProfile.people.create_user(
            email = validated_data['email'],
            name  = validated_data['name'],
            password = make_password(validated_data['password']) # here
        )
        return user

Or

if you don't override the .create() method then add the following validate_password method in serializer, The validate_password is ran, everytime a new object has to be created

class UserProfileSerializer(serializers.ModelSerializer):    
    class Meta:
        model        = UserProfile
        fields       = ('id' ,'email' ,'name' ,'password')
        extra_kwargs = {
            'password':{
                'write_only':'True',
                'style': {'input_type': 'password'}
            }
        } 
    def validate_password(self, value: str) -> str:
        return make_password(value)

Upvotes: 1

Related Questions