From 1d0cc52e07fe261a34b6d1ed44cf7d7a84539773 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Mon, 14 Aug 2023 21:50:02 +0300 Subject: [PATCH 01/13] add graphene3 support --- graphql_auth/mixins.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphql_auth/mixins.py b/graphql_auth/mixins.py index ba2d184..3c4c9b2 100644 --- a/graphql_auth/mixins.py +++ b/graphql_auth/mixins.py @@ -74,8 +74,8 @@ class RegisterMixin(Output): def Field(cls, *args, **kwargs): if app_settings.ALLOW_LOGIN_NOT_VERIFIED: if using_refresh_tokens(): - cls._meta.fields["refresh_token"] = graphene.Field(graphene.String) - cls._meta.fields["token"] = graphene.Field(graphene.String) + setattr(cls, "refresh_token", graphene.Field(graphene.String)) + setattr(cls, "token", graphene.Field(graphene.String)) return super().Field(*args, **kwargs) @classmethod From fcfdb422f9b02fcd784fada232888e2da5b34360 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Mon, 14 Aug 2023 22:28:42 +0300 Subject: [PATCH 02/13] wip --- setup.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/setup.py b/setup.py index 8ec02de..79b3798 100644 --- a/setup.py +++ b/setup.py @@ -41,14 +41,6 @@ def get_version(package): ) ), packages=find_packages(exclude=["tests*"]), - install_requires=[ - "Django>=2.2.0", - "django-graphql-jwt==0.3.0", - "django-filter>=2.2.0", - "graphene_django>=2.1.8", - "graphene>=2.1.8", - "PyJWT<2.0.0", - ], tests_require=tests_require, classifiers=[ "Development Status :: 4 - Beta", From 1246203343948afaa5ee5bbb2cf3ceb2a12f3252 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Mon, 14 Aug 2023 22:36:38 +0300 Subject: [PATCH 03/13] wip --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index 79b3798..82e6231 100644 --- a/setup.py +++ b/setup.py @@ -41,6 +41,9 @@ def get_version(package): ) ), packages=find_packages(exclude=["tests*"]), + install_requires=[ + "django-graphql-jwt==0.4.0", + ], tests_require=tests_require, classifiers=[ "Development Status :: 4 - Beta", From 7d5e2325fb35ae293da8097c9e00528ab27f0498 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 00:23:46 +0300 Subject: [PATCH 04/13] wip --- graphql_auth/mixins.py | 15 +++++++-------- setup.py | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/graphql_auth/mixins.py b/graphql_auth/mixins.py index 3c4c9b2..9aab67e 100644 --- a/graphql_auth/mixins.py +++ b/graphql_auth/mixins.py @@ -41,7 +41,14 @@ else: async_email_func = None +def add_dynamic_fields(cls): + if app_settings.ALLOW_LOGIN_NOT_VERIFIED: + setattr(cls, "token", graphene.Field(graphene.String)) + if using_refresh_tokens(): + setattr(cls, "refresh_token", graphene.Field(graphene.String)) + return cls +@add_dynamic_fields class RegisterMixin(Output): """ Register user with fields defined in the settings. @@ -70,14 +77,6 @@ class RegisterMixin(Output): else RegisterForm ) - @classmethod - def Field(cls, *args, **kwargs): - if app_settings.ALLOW_LOGIN_NOT_VERIFIED: - if using_refresh_tokens(): - setattr(cls, "refresh_token", graphene.Field(graphene.String)) - setattr(cls, "token", graphene.Field(graphene.String)) - return super().Field(*args, **kwargs) - @classmethod @token_auth def login_on_register(cls, root, info, **kwargs): diff --git a/setup.py b/setup.py index 82e6231..ac17f79 100644 --- a/setup.py +++ b/setup.py @@ -43,6 +43,7 @@ def get_version(package): packages=find_packages(exclude=["tests*"]), install_requires=[ "django-graphql-jwt==0.4.0", + "PyJWT==2.8.0", ], tests_require=tests_require, classifiers=[ From 8c772aff66722b9e1596a7235e0d9742cf248ec8 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 01:51:47 +0300 Subject: [PATCH 05/13] wip --- graphql_auth/mixins.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/graphql_auth/mixins.py b/graphql_auth/mixins.py index 9aab67e..366673a 100644 --- a/graphql_auth/mixins.py +++ b/graphql_auth/mixins.py @@ -476,7 +476,7 @@ def resolve_action(cls, user, *args, **kwargs): user.save(update_fields=["is_active"]) revoke_user_refresh_token(user=user) - +@add_dynamic_fields class PasswordChangeMixin(Output): """ Change account password when user knows the old password. @@ -486,13 +486,6 @@ class PasswordChangeMixin(Output): form = PasswordChangeForm - @classmethod - def Field(cls, *args, **kwargs): - if using_refresh_tokens(): - cls._meta.fields["refresh_token"] = graphene.Field(graphene.String) - cls._meta.fields["token"] = graphene.Field(graphene.String) - return super().Field(*args, **kwargs) - @classmethod @token_auth def login_on_password_change(cls, root, info, **kwargs): From a0a83ac218525c55010a0db9e02aac9ae26e212f Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 05:22:55 +0300 Subject: [PATCH 06/13] wip --- graphql_auth/mixins.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/graphql_auth/mixins.py b/graphql_auth/mixins.py index 366673a..28462d9 100644 --- a/graphql_auth/mixins.py +++ b/graphql_auth/mixins.py @@ -41,14 +41,7 @@ else: async_email_func = None -def add_dynamic_fields(cls): - if app_settings.ALLOW_LOGIN_NOT_VERIFIED: - setattr(cls, "token", graphene.Field(graphene.String)) - if using_refresh_tokens(): - setattr(cls, "refresh_token", graphene.Field(graphene.String)) - return cls -@add_dynamic_fields class RegisterMixin(Output): """ Register user with fields defined in the settings. @@ -76,6 +69,15 @@ class RegisterMixin(Output): if app_settings.ALLOW_PASSWORDLESS_REGISTRATION else RegisterForm ) + + @classmethod + def Field(cls, *args, **kwargs): + if app_settings.ALLOW_LOGIN_NOT_VERIFIED: + if using_refresh_tokens(): + cls._meta.fields["refresh_token"] = graphene.Field(graphene.String) + cls._meta.fields["token"] = graphene.Field(graphene.String) + return super().Field(*args, **kwargs) + @classmethod @token_auth @@ -476,7 +478,7 @@ def resolve_action(cls, user, *args, **kwargs): user.save(update_fields=["is_active"]) revoke_user_refresh_token(user=user) -@add_dynamic_fields + class PasswordChangeMixin(Output): """ Change account password when user knows the old password. @@ -486,6 +488,13 @@ class PasswordChangeMixin(Output): form = PasswordChangeForm + @classmethod + def Field(cls, *args, **kwargs): + if using_refresh_tokens(): + cls._meta.fields["refresh_token"] = graphene.Field(graphene.String) + cls._meta.fields["token"] = graphene.Field(graphene.String) + return super().Field(*args, **kwargs) + @classmethod @token_auth def login_on_password_change(cls, root, info, **kwargs): From 5d0d702acf26ade2bf8316a436373909f658429c Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 05:33:28 +0300 Subject: [PATCH 07/13] wip --- graphql_auth/mixins.py | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/graphql_auth/mixins.py b/graphql_auth/mixins.py index 28462d9..366673a 100644 --- a/graphql_auth/mixins.py +++ b/graphql_auth/mixins.py @@ -41,7 +41,14 @@ else: async_email_func = None +def add_dynamic_fields(cls): + if app_settings.ALLOW_LOGIN_NOT_VERIFIED: + setattr(cls, "token", graphene.Field(graphene.String)) + if using_refresh_tokens(): + setattr(cls, "refresh_token", graphene.Field(graphene.String)) + return cls +@add_dynamic_fields class RegisterMixin(Output): """ Register user with fields defined in the settings. @@ -69,15 +76,6 @@ class RegisterMixin(Output): if app_settings.ALLOW_PASSWORDLESS_REGISTRATION else RegisterForm ) - - @classmethod - def Field(cls, *args, **kwargs): - if app_settings.ALLOW_LOGIN_NOT_VERIFIED: - if using_refresh_tokens(): - cls._meta.fields["refresh_token"] = graphene.Field(graphene.String) - cls._meta.fields["token"] = graphene.Field(graphene.String) - return super().Field(*args, **kwargs) - @classmethod @token_auth @@ -478,7 +476,7 @@ def resolve_action(cls, user, *args, **kwargs): user.save(update_fields=["is_active"]) revoke_user_refresh_token(user=user) - +@add_dynamic_fields class PasswordChangeMixin(Output): """ Change account password when user knows the old password. @@ -488,13 +486,6 @@ class PasswordChangeMixin(Output): form = PasswordChangeForm - @classmethod - def Field(cls, *args, **kwargs): - if using_refresh_tokens(): - cls._meta.fields["refresh_token"] = graphene.Field(graphene.String) - cls._meta.fields["token"] = graphene.Field(graphene.String) - return super().Field(*args, **kwargs) - @classmethod @token_auth def login_on_password_change(cls, root, info, **kwargs): From 6d0b7201e1762d82eda7fe15ebdede603b5f6af4 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 06:50:27 +0300 Subject: [PATCH 08/13] wip --- graphql_auth/mutations.py | 49 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/graphql_auth/mutations.py b/graphql_auth/mutations.py index 71ac4b3..8050d6c 100644 --- a/graphql_auth/mutations.py +++ b/graphql_auth/mutations.py @@ -1,5 +1,9 @@ import graphene import graphql_jwt +from django.contrib.auth import get_user_model +from graphql_jwt.decorators import token_auth +from graphene.types.generic import GenericScalar +from graphql_jwt.settings import jwt_settings from .bases import MutationMixin, DynamicArgsMixin from .mixins import ( @@ -24,6 +28,49 @@ from .settings import graphql_auth_settings as app_settings from .schema import UserNode +class CustomObtainJSONWebTokenMixin: + payload = GenericScalar() + refresh_expires_in = graphene.Int(required=True) + + @classmethod + def Field(cls, *args, **kwargs): + if not jwt_settings.JWT_HIDE_TOKEN_FIELDS: + cls._meta.fields["token"] = graphene.Field(graphene.String) + + if jwt_settings.JWT_LONG_RUNNING_REFRESH_TOKEN: + cls._meta.fields["refresh_token"] = graphene.Field( + graphene.String, + ) + + return super().Field(*args, **kwargs) + + @classmethod + def __init_subclass_with_meta__(cls, name=None, **options): + assert getattr(cls, "resolve", None), ( + f"{name or cls.__name__}.resolve " + "method is required in a JSONWebTokenMutation." + ) + + super().__init_subclass_with_meta__(name=name, **options) + +class JSONWebTokenMutation(CustomObtainJSONWebTokenMixin, graphene.Mutation): + class Meta: + abstract = True + + @classmethod + def Field(cls, *args, **kwargs): + cls._meta.arguments.update( + { + get_user_model().USERNAME_FIELD: graphene.String(required=True), + "password": graphene.String(required=True), + }, + ) + return super().Field(*args, **kwargs) + + @classmethod + @token_auth + def mutate(cls, root, info, **kwargs): + return cls.resolve(root, info, **kwargs) class Register(MutationMixin, DynamicArgsMixin, RegisterMixin, graphene.Mutation): @@ -103,7 +150,7 @@ class PasswordReset( class ObtainJSONWebToken( - MutationMixin, ObtainJSONWebTokenMixin, graphql_jwt.JSONWebTokenMutation + MutationMixin, ObtainJSONWebTokenMixin, JSONWebTokenMutation ): __doc__ = ObtainJSONWebTokenMixin.__doc__ user = graphene.Field(UserNode) From 87d078f3c38c2fed12147b9cbd93aefa6de9204d Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 06:51:51 +0300 Subject: [PATCH 09/13] wip --- graphql_auth/mutations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql_auth/mutations.py b/graphql_auth/mutations.py index 8050d6c..8d3cbe4 100644 --- a/graphql_auth/mutations.py +++ b/graphql_auth/mutations.py @@ -30,7 +30,7 @@ class CustomObtainJSONWebTokenMixin: payload = GenericScalar() - refresh_expires_in = graphene.Int(required=True) + refresh_expires_in = graphene.Int() @classmethod def Field(cls, *args, **kwargs): From cc928e98c597e099acde625a1fde41e747b46d11 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 16:47:41 +0300 Subject: [PATCH 10/13] wip --- graphql_auth/mutations.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/graphql_auth/mutations.py b/graphql_auth/mutations.py index 8d3cbe4..d16fa04 100644 --- a/graphql_auth/mutations.py +++ b/graphql_auth/mutations.py @@ -156,13 +156,6 @@ class ObtainJSONWebToken( user = graphene.Field(UserNode) unarchiving = graphene.Boolean(default_value=False) - @classmethod - def Field(cls, *args, **kwargs): - cls._meta.arguments.update({"password": graphene.String(required=True)}) - for field in app_settings.LOGIN_ALLOWED_FIELDS: - cls._meta.arguments.update({field: graphene.String()}) - return super(graphql_jwt.JSONWebTokenMutation, cls).Field(*args, **kwargs) - class ArchiveAccount( MutationMixin, ArchiveAccountMixin, DynamicArgsMixin, graphene.Mutation From 8ff83c6167bdfc92cef3575459776bcfa2319b15 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 17:33:05 +0300 Subject: [PATCH 11/13] wip --- graphql_auth/mixins.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/graphql_auth/mixins.py b/graphql_auth/mixins.py index 366673a..56a885e 100644 --- a/graphql_auth/mixins.py +++ b/graphql_auth/mixins.py @@ -42,10 +42,9 @@ async_email_func = None def add_dynamic_fields(cls): - if app_settings.ALLOW_LOGIN_NOT_VERIFIED: - setattr(cls, "token", graphene.Field(graphene.String)) - if using_refresh_tokens(): - setattr(cls, "refresh_token", graphene.Field(graphene.String)) + setattr(cls, "token", graphene.Field(graphene.String)) + if using_refresh_tokens(): + setattr(cls, "refresh_token", graphene.Field(graphene.String)) return cls @add_dynamic_fields From ae231788a80994afd812f36df6389c9b05551a2e Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 18:04:04 +0300 Subject: [PATCH 12/13] wip --- graphql_auth/mutations.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/graphql_auth/mutations.py b/graphql_auth/mutations.py index d16fa04..d18eaeb 100644 --- a/graphql_auth/mutations.py +++ b/graphql_auth/mutations.py @@ -4,6 +4,7 @@ from graphql_jwt.decorators import token_auth from graphene.types.generic import GenericScalar from graphql_jwt.settings import jwt_settings +from graphql_jwt.mixins import RefreshTokenMixin, KeepAliveRefreshMixin from .bases import MutationMixin, DynamicArgsMixin from .mixins import ( @@ -72,6 +73,26 @@ def Field(cls, *args, **kwargs): def mutate(cls, root, info, **kwargs): return cls.resolve(root, info, **kwargs) +class RefreshMixin( + ( + RefreshTokenMixin + if jwt_settings.JWT_LONG_RUNNING_REFRESH_TOKEN + else KeepAliveRefreshMixin + ), + CustomObtainJSONWebTokenMixin, +): + """RefreshMixin""" + + +class CustomRefresh(RefreshMixin, graphene.Mutation): + class Arguments(RefreshMixin.Fields): + """Refresh Arguments""" + + @classmethod + def mutate(cls, *arg, **kwargs): + return cls.refresh(*arg, **kwargs) + + class Register(MutationMixin, DynamicArgsMixin, RegisterMixin, graphene.Mutation): __doc__ = RegisterMixin.__doc__ @@ -190,7 +211,7 @@ class VerifyToken(MutationMixin, VerifyOrRefreshOrRevokeTokenMixin, graphql_jwt. class RefreshToken( - MutationMixin, VerifyOrRefreshOrRevokeTokenMixin, graphql_jwt.Refresh + MutationMixin, VerifyOrRefreshOrRevokeTokenMixin, CustomRefresh ): __doc__ = VerifyOrRefreshOrRevokeTokenMixin.__doc__ From 1a33e0b35e4be300ac165ce8dd68c500864b6e18 Mon Sep 17 00:00:00 2001 From: Mng <50384638+Mng-dev-ai@users.noreply.github.com> Date: Tue, 15 Aug 2023 18:13:01 +0300 Subject: [PATCH 13/13] wip --- graphql_auth/mutations.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/graphql_auth/mutations.py b/graphql_auth/mutations.py index d18eaeb..780a8df 100644 --- a/graphql_auth/mutations.py +++ b/graphql_auth/mutations.py @@ -29,7 +29,7 @@ from .settings import graphql_auth_settings as app_settings from .schema import UserNode -class CustomObtainJSONWebTokenMixin: +class JSONWebTokenMixin: payload = GenericScalar() refresh_expires_in = graphene.Int() @@ -44,7 +44,8 @@ def Field(cls, *args, **kwargs): ) return super().Field(*args, **kwargs) - + +class CustomObtainJSONWebTokenMixin(JSONWebTokenMixin): @classmethod def __init_subclass_with_meta__(cls, name=None, **options): assert getattr(cls, "resolve", None), ( @@ -79,7 +80,7 @@ class RefreshMixin( if jwt_settings.JWT_LONG_RUNNING_REFRESH_TOKEN else KeepAliveRefreshMixin ), - CustomObtainJSONWebTokenMixin, + JSONWebTokenMixin, ): """RefreshMixin"""