From 2a7dd043588a61cc8675b218d117dc40544fd115 Mon Sep 17 00:00:00 2001 From: Philipp Schmitt Date: Thu, 14 Nov 2024 17:52:39 +0100 Subject: [PATCH 1/6] BA-1808 [BE] Add .distinct() when filtering profiles --- baseapp-auth/baseapp_auth/graphql/object_types.py | 2 +- baseapp-profiles/baseapp_profiles/managers.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/baseapp-auth/baseapp_auth/graphql/object_types.py b/baseapp-auth/baseapp_auth/graphql/object_types.py index e7ee733f..a9d77807 100644 --- a/baseapp-auth/baseapp_auth/graphql/object_types.py +++ b/baseapp-auth/baseapp_auth/graphql/object_types.py @@ -48,7 +48,7 @@ def resolve_profiles(self, info): return Profile.objects.none() return Profile.objects.filter( Q(owner_id=info.context.user.id) | Q(members__user_id=info.context.user.id) - ) + ).distinct() interfaces += (UserProfiles, ProfileInterface) diff --git a/baseapp-profiles/baseapp_profiles/managers.py b/baseapp-profiles/baseapp_profiles/managers.py index d6cf1347..aff95e85 100644 --- a/baseapp-profiles/baseapp_profiles/managers.py +++ b/baseapp-profiles/baseapp_profiles/managers.py @@ -3,7 +3,7 @@ class ProfileManager(models.Manager): def filter_user_profiles(self, user): - return self.filter(models.Q(members__user=user) | models.Q(owner=user)) + return self.filter(models.Q(members__user=user) | models.Q(owner=user)).distinct() def get_if_member(self, user, **kwargs): if user.is_superuser: From 338feaf676eb398eec96a5319e345442c736f311 Mon Sep 17 00:00:00 2001 From: Philipp Schmitt Date: Thu, 14 Nov 2024 17:53:20 +0100 Subject: [PATCH 2/6] BA-1808 [BE] add profile key to user serializer --- .../rest_framework/users/serializers.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py b/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py index e057c3b1..274ae179 100644 --- a/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py +++ b/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py @@ -1,3 +1,5 @@ +import swapper + from datetime import timedelta from baseapp_auth.utils.referral_utils import get_user_referral_model, use_referrals @@ -14,21 +16,29 @@ from .fields import AvatarField User = get_user_model() +Profile = swapper.load_model("baseapp_profiles", "Profile") from baseapp_auth.password_validators import apply_password_validators +class ProfileSerializer(ModelSerializer): + url_path = serializers.SlugField(required=False) + + class Meta: + model = Profile + fields = ("id", "name", "image", "url_path") + class UserBaseSerializer(ModelSerializer): - name = serializers.CharField(required=False, allow_blank=True, source="first_name") - avatar = AvatarField(required=False, allow_null=True) + profile = ProfileSerializer(read_only=True) email_verification_required = serializers.SerializerMethodField() referral_code = serializers.SerializerMethodField() referred_by_code = serializers.CharField(required=False, allow_blank=True, write_only=True) - + class Meta: model = User fields = ( "id", + "profile", "email", "is_email_verified", "email_verification_required", @@ -36,8 +46,6 @@ class Meta: "is_new_email_confirmed", "referral_code", "referred_by_code", - "avatar", - "name", "phone_number", "preferred_language", ) From dd0fd038f21a825aed60919b72ce70b741a8fcac Mon Sep 17 00:00:00 2001 From: Philipp Schmitt Date: Thu, 21 Nov 2024 17:56:26 -0500 Subject: [PATCH 3/6] BA-1808 pass context to claim serializer This allows the claim serializer to convert the profile image urls into absolute urls. --- .../baseapp_auth/rest_framework/jwt/serializers.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/baseapp-auth/baseapp_auth/rest_framework/jwt/serializers.py b/baseapp-auth/baseapp_auth/rest_framework/jwt/serializers.py index ee07c6a7..eef80b0f 100644 --- a/baseapp-auth/baseapp_auth/rest_framework/jwt/serializers.py +++ b/baseapp-auth/baseapp_auth/rest_framework/jwt/serializers.py @@ -26,13 +26,12 @@ def get_claim_serializer_class(cls): class BaseJwtLoginSerializer( CustomClaimSerializerMixin, LoginPasswordExpirationMixin, TokenObtainPairSerializer ): - @classmethod - def get_token(cls, user): + def get_token(self, user): token = super().get_token(user) # Add custom claims - if cls._claim_serializer_class: - data = cls.get_claim_serializer_class()(user).data + if self._claim_serializer_class: + data = self.get_claim_serializer_class()(user, context=self.context).data for key, value in data.items(): token[key] = value From 050e8b0d30eba1e04063972828fde0528d75d522 Mon Sep 17 00:00:00 2001 From: Philipp Schmitt Date: Thu, 21 Nov 2024 17:57:14 -0500 Subject: [PATCH 4/6] BA-1808 Pass profile image also in small resolution --- baseapp-auth/baseapp_auth/rest_framework/users/serializers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py b/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py index 274ae179..171aacb4 100644 --- a/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py +++ b/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py @@ -4,6 +4,7 @@ from baseapp_auth.utils.referral_utils import get_user_referral_model, use_referrals from baseapp_core.rest_framework.serializers import ModelSerializer +from baseapp_core.rest_framework.fields import ThumbnailImageField from baseapp_referrals.utils import get_referral_code, get_user_from_referral_code from constance import config from django.contrib.auth import get_user_model @@ -22,6 +23,7 @@ class ProfileSerializer(ModelSerializer): url_path = serializers.SlugField(required=False) + image = ThumbnailImageField(required=False, sizes={"small": (100,100)}) class Meta: model = Profile From 55fd0c2b49557b3ef7fcfce061f74d664e65bbc5 Mon Sep 17 00:00:00 2001 From: Philipp Schmitt Date: Mon, 25 Nov 2024 15:03:08 -0500 Subject: [PATCH 5/6] BA-1808 Serialize profile id as relay id --- .../rest_framework/users/serializers.py | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py b/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py index 171aacb4..20766b21 100644 --- a/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py +++ b/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py @@ -3,6 +3,7 @@ from datetime import timedelta from baseapp_auth.utils.referral_utils import get_user_referral_model, use_referrals +from baseapp_core.graphql import get_obj_relay_id from baseapp_core.rest_framework.serializers import ModelSerializer from baseapp_core.rest_framework.fields import ThumbnailImageField from baseapp_referrals.utils import get_referral_code, get_user_from_referral_code @@ -21,17 +22,32 @@ from baseapp_auth.password_validators import apply_password_validators -class ProfileSerializer(ModelSerializer): - url_path = serializers.SlugField(required=False) - image = ThumbnailImageField(required=False, sizes={"small": (100,100)}) +class JWTProfileSerializer(serializers.ModelSerializer): + """ + Serializes minimal profile data that will be attached to the JWT token as claim + """ + url_path = serializers.SerializerMethodField() # serializers.SlugField(required=False) + id = serializers.SerializerMethodField() + image = ThumbnailImageField(required=False, sizes={"url": (100,100)}) class Meta: model = Profile fields = ("id", "name", "image", "url_path") + def get_url_path(self, profile): + return { 'path': profile.url_path.path} + + def get_id(self, profile): + return get_obj_relay_id(profile) + + def to_representation(self, instance): + data = super().to_representation(instance) + data['image'].pop('full_size') + return data + class UserBaseSerializer(ModelSerializer): - profile = ProfileSerializer(read_only=True) + profile = JWTProfileSerializer(read_only=True) email_verification_required = serializers.SerializerMethodField() referral_code = serializers.SerializerMethodField() referred_by_code = serializers.CharField(required=False, allow_blank=True, write_only=True) From 23df42df999602d0856fbbae49e8253bf5d2ad39 Mon Sep 17 00:00:00 2001 From: Philipp Schmitt Date: Wed, 27 Nov 2024 10:26:53 -0500 Subject: [PATCH 6/6] BA-1808 Change JWT profile serializer to simplify data structure --- .../rest_framework/users/serializers.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py b/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py index 20766b21..ba2d30bb 100644 --- a/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py +++ b/baseapp-auth/baseapp_auth/rest_framework/users/serializers.py @@ -22,27 +22,26 @@ from baseapp_auth.password_validators import apply_password_validators + class JWTProfileSerializer(serializers.ModelSerializer): """ Serializes minimal profile data that will be attached to the JWT token as claim """ - url_path = serializers.SerializerMethodField() # serializers.SlugField(required=False) + url_path = serializers.SlugField(required=False) id = serializers.SerializerMethodField() - image = ThumbnailImageField(required=False, sizes={"url": (100,100)}) + image = ThumbnailImageField(required=False, sizes={"small": (100,100)}) class Meta: model = Profile fields = ("id", "name", "image", "url_path") - def get_url_path(self, profile): - return { 'path': profile.url_path.path} - def get_id(self, profile): return get_obj_relay_id(profile) - def to_representation(self, instance): - data = super().to_representation(instance) - data['image'].pop('full_size') + def to_representation(self, profile): + data = super().to_representation(profile) + if (data['image'] != None): + data['image'] = data['image']['small'] return data