2

I am creating a user by sending a POST request through an android app with the request containing a username, password, and email-id. Now in my app, there are two kinds of users i.e. Teachers and Students. Now for distinguishing between teachers and students during signup I want to send a verification email to the teacher comprising of a randomly generated token. Now I want the teacher to enter this token during the signup to verify that actually, a teacher is signing up and not some mischievous student who just wants to mess up with everyone. I am able to send email containing a token but cannot understand that how will I verify it when the teacher enters the token on the app while signing up, matches with the token sent to the email-id.

Below is the code of my serializer used to send the email containing a token

class UserSerializer(serializers.ModelSerializer):
    token = serializers.CharField(max_length=100, null=True, blank=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'email', 'token')

    def create(self, validated_data):
        user = User(username=validated_data['username'], 
        email=validated_data['email'])
        user.set_password(validated_data['password'])
        user.save()

        subject = "Email verification for django"
        message = account_activation_token.make_token(user)
        send_mail(subject, message, settings.EMAIL_HOST_USER, 
        [user.email])
        return user

As you peeps can see, in the above code I am generating a random token and sending the email when I get a POST request for creating a new user. Now my user will enter the token from the email in the app and send a POST request. Now I want to check whether the token entered by the user is same as the token generated above in the code so that I can verify the user and proceed with the signup form.

PS: My User model doesn't contain a token field as I am using the inbuilt user model provided by Django and connecting it to the Teacher model using a One-To-One-Field

PPS: Is there any other way that I can use to implement the above functionality?

2 Answers 2

3

You need to save the token on your side (database) to match it with the one the teacher inputs into your form. So make a model first.

class Token(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    token = models.CharField(max_length=255)

The line that generates the token comes AFTER the user is created, so you can just use the user instance and save the token on to the model that you just created:

def create(self, validated_data):
    ...
    message = account_activation_token.make_token(user)
    Token.objects.create(user=user, token=message)
    send_mail(subject, message, settings.EMAIL_HOST_USER,
    ...

Next you use the following code in your view to check if the user have inputed the correct token:

...
token_obj = Token.objects.get(user=user)
user_token = token_obj.token
if form.data['token'] == user_token:
    # code to accept the user
    token_obj.delete() # this deletes the row since you will not use it anymore
else:
    # code to reject the user

Note: Please don't copy paste these codes. Adjust accordingly.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer. I think so this may work for me pretty well, but if it could be more robust because ultimately you are going to delete the token from the database as it is just used for verification. Also, how do many of the big companies do their signup from android app?
I don't suppose their is a problem if the tokens are not deleted. However, you can add a code once the verification is complete to delete the row from the database. I am not quite sure how the big companies do it as I'm not an app developer, neither have I ever worked with DRF. I have updated the code in the answer to delete the row. If my answer has helped you please upvote and accept. Thanks. :)
0

I would rather use def validate_* where * can be any field (for field level validation) as mentioned in DRF docs:

from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer

from .models import SomeModel


class SomeModelSerializer(ModelSerializer):
    class Meta:
        model = SomeModel
        fields = (
            "email",
            "password",
        )

    def create(self, validated_data):
        user = SomeModel.objects.create_user(**validated_data)
        return user

    def validate_email(self, email):
        try:
            validate_email(email)
        except ValidationError:
            raise serializers.ValidationError('email is invalid')    
        return email

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.