Tuesday, 6 December 2022

Extending django-graphql-auth to constrain username, passwords and emails

I am using Django v 3.2 and django-graphql-auth v 0.3.16

I have a custom User (and User Manager) defined like this:

models.py

class CustomUser(AbstractUser):
    USERNAME_FIELD='username'
    EMAIL_FIELD='email'
    # ...

    objects = CustomUserManager()

managers.py

class CustomUserManager(BaseUserManager):
    # ...
    def create_user(self, email, password, **extra_fields):
        if not is_valid_email(email):
            raise ValueError(_('Bad email'))

        username = extra_fields.get('username')

        if not is_acceptable_username(username)):
            raise ValueError(_('You cannot use this username'))

        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 a SuperUser with the 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)

settings.py

# ....
AUTH_USER_MODEL='myapp.CustomUser'

schema.py

import graphene
from graphql_auth import mutations
from graphql_auth.schema import MeQuery, UserQuery



class AuthMutation(graphene.ObjectType):
    register = mutations.Register.Field()
    verify_account = mutations.VerifyAccount.Field()


class Query(UserQuery, MeQuery, graphene.ObjectType):
    pass


class Mutation(AuthMutation, graphene.ObjectType):
    pass


schema = graphene.Schema(query=Query, mutation=Mutation)

I try to register a new user through the following mutation:

mutation {
  register(
        email: "memyself@somebad-domain.com",
      username: "badword1",
      password1: "1234",
      password2: "1234"
  ) {
    success
    errors
    token
  }
}

And I get the following response:

{
  "data": {
    "register": {
      "success": true,
      "errors": null,
      "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImJhZHdvcmQxIiwiZXhwIjoxNjY5OTEzNDIzLCJvcmlnSWF0IjoxNjY5OTEzMTIzfQ.TZ-copVrhUUsuLpozi18THjprGMnAGsBwpnyWORc16M"
    }
  }
}

The expected result would be that the GraphQL mutation will return a failure code, based on the email, username and password - all of which have been specified intentionally to be rejected.

Why is django-graphql-auth not using my custom manager to create objects - and how do I fix it so that I can implement my own validations (e.g. to correctly check/validate username and email)?



from Extending django-graphql-auth to constrain username, passwords and emails

No comments:

Post a Comment