nrbnlulu / strawberry-django-auth

Authentication system for django using strawberry
https://nrbnlulu.github.io/strawberry-django-auth/
MIT License
65 stars 30 forks source link

Allow modify UserType fields to return or filter extra information of the custom user #264

Open LinnaViljami opened 1 year ago

LinnaViljami commented 1 year ago

Description

Allow modify UserType fields to return or filter extra information of the custom user

Expected behavior

All CustomUser model fields should be returned along UserType in mutations and queries.

Returned fields should be able to controlled with django setting, for example FILTER_USER_FIELDS = ['customField1', 'customField2', ...].

The best and most flexible solution could allow calculate extra information without even defining new field to user model but instead just define property or custom function and return a calculated value in graphql response along the other fields of the UserType.

Actual behavior

Currently UserType can be modified only through the USER_FIELDS, with USER_MODEL.USERNAME_FIELD, USER_MODEL.EMAIL_FIELD or gqlauth_settings.UPDATE_MUTATION_FIELDS. This is not enough if we want to define a custom non pk field that user can not modify through mutation.

Requirements

strawberry-django-auth 0.374

nrbnlulu commented 1 year ago

The best and most flexible solution could allow calculate extra information without even defining new field to user model but instead just define https://github.com/Property or custom function and return a calculated value in graphql response along the other fields of the UserType.

you link is broken, can you share a minimal example of what you suggest?

Currently UserType can be modified only through the USER_FIELDS, with USER_MODEL.USERNAME_FIELD, USER_MODEL.EMAIL_FIELD or gqlauth_settings.UPDATE_MUTATION_FIELDS. This is not enough if we want to define a custom non pk field that user can not modify through mutation.

IIRC UPDATE_MUTATION_FIELDS can accept any StrawberryField and it would be injected to UserType

LinnaViljami commented 1 year ago

So the problem is that injecting an extra field to the UserType is not flexible enough, because by doing so, we allow both: UPDATE the field and READ the field.

So basically the lacking feature is, to add read-only fields/information to the user, which COULD BE QUERIED along with user information (when querying UserType), BUT CAN NOT BE MODIFIED through updateUser mutation

LinnaViljami commented 1 year ago

And I suggested some possible solutions

  1. Define custom setting that injects UserModel fields to the returned UserType, but does not add these fields to the parameters of updateUser mutation.
  2. Even more flexible solution would allow inject some extra information to the returned user type. So for example somehow calculate new field which is not a databasefield or field of the UserModel.

The broken link was not meant to be link but I was just speaking python properties, check this for more information, to demonstrate how we may want calculate extra information of the user but not defining an actual field to the model.

nrbnlulu commented 1 year ago

@LinnaViljami I think I would just add GqlAuthSettings.USER_TYPE, then you would have to derive from the original UserType and provide that in GqlAuthSettings as for UPDATE_MUTATION_FIELDS they would just be List[str]. what do you think? This can be the path to solve #265 too...

LinnaViljami commented 1 year ago

I agree, the idea sounds logical (returned UserType being separated from the editable fields)

I am quite a beginner with strawberry graphql (I mostly use graphql-django), so I am not sure if then UserType should be defined as interface to allow inheritance. But without considering the technical details, your approach sounds good.

Could you post an minimal example how then would be possible to: a) Return extra fields of the CustomUser model along with UserType b) Add custom resolvers and thus return a field along with UserType that even does not exist on your CustomUser model

nrbnlulu commented 1 year ago

~

class MyUserModel(AbstractUserModel):  # ideally `AbstractUserModel` would be provided by gqlauth
    some_cool_field: models.CharField()

@strawberry_django.type(model=MyUserModel)
class MyUserType(GqlAuthUserInterface):
    some_cool_field: auto
    @strawberry.field
    def field_not_in_model(self) -> int:
        return 2
micrypt commented 1 year ago

We currently have a Profile model connected to from django.contrib.auth.models.User.

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

In the Graphene implementation, this meant we could reference it as follows:

user {
  id
  profile {
     ...
  }
}

This is proving challenging to replicate on moving across to Strawberry, resulting in the following error: Cannot query field 'profile' on type 'UserType'.

MaximeDetne commented 9 months ago

Any updates on that ?

nrbnlulu commented 9 months ago

Not ATM sorry I don't have much time recently. You can open a PR though.