Coverage for apps/users/serializers.py: 60%

135 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2024-05-15 10:51 -0600

1from django.conf import settings 

2from django.contrib.auth.password_validation import validate_password 

3from django.contrib.auth.tokens import PasswordResetTokenGenerator 

4from rest_framework import serializers 

5from rest_framework.validators import ValidationError 

6from dj_rest_auth.serializers import UserDetailsSerializer 

7 

8from apps.organizations.models import Affiliation, OrganizationRole 

9from apps.practitioners.serializers import PractitionerSerializer 

10from services.google import GoogleService 

11 

12from .models import GoogleAccount, User 

13 

14 

15class GoogleAccountSerializer(serializers.ModelSerializer): 

16 class Meta: 

17 model = GoogleAccount 

18 read_only_fields = ["state", "auth_url"] 

19 fields = read_only_fields + [] 

20 

21 def create(self, validated_data): 

22 google_service = GoogleService() 

23 flow = google_service._create_flow() 

24 auth_url, state = google_service._get_auth_url_and_state() 

25 validated_data.update( 

26 { 

27 "state": state, 

28 "auth_url": auth_url, 

29 } 

30 ) 

31 instance = super().create(validated_data) 

32 return instance 

33 

34 

35class GoogleValidateSerializer(serializers.ModelSerializer): 

36 code = serializers.CharField() 

37 

38 class Meta: 

39 model = GoogleAccount 

40 read_only_fields = [] 

41 fields = read_only_fields + ["code"] 

42 

43 def update(self, instance, validated_data): 

44 code = validated_data.pop("code") 

45 state = instance.state 

46 try: 

47 google_service = GoogleService() 

48 flow = google_service._get_flow_by_state(state=state) 

49 fetch_token = google_service._get_flow_token(code=code) 

50 credentials = google_service._get_credentials_from_flow() 

51 instance.credentials_json = credentials.to_json() 

52 instance.token = credentials.token 

53 instance.code = code 

54 instance.refresh_token = credentials.refresh_token 

55 instance.expires_at = credentials.expiry 

56 instance.awaiting_code = False 

57 instance.save() 

58 except Exception as e: 

59 print(e) 

60 return super().update(instance, validated_data) 

61 

62 

63class OrganizationRoleSerializerForUser(serializers.ModelSerializer): 

64 role_type = serializers.CharField(source="role_type.type_of") 

65 

66 class Meta: 

67 model = OrganizationRole 

68 read_only_fields = ["role_type"] 

69 fields = ["name", "role_type", "random_slug"] 

70 

71 

72class AffiliationSerializerForUser(serializers.ModelSerializer): 

73 """ 

74 Serailizer for Affiliation 

75 """ 

76 

77 roles = OrganizationRoleSerializerForUser(many=True, read_only=True) 

78 

79 class Meta: 

80 model = Affiliation 

81 fields = ["organization", "roles", "is_owner"] 

82 

83 

84class UserSerializer(serializers.ModelSerializer): 

85 """ 

86 Serializer for User 

87 """ 

88 

89 practitioner = PractitionerSerializer(read_only=True) 

90 affiliations = AffiliationSerializerForUser(many=True, read_only=True) 

91 google_account = serializers.SerializerMethodField() 

92 

93 class Meta: 

94 model = User 

95 read_only_fields = ["id", "practitioner", "affiliations", "google_account"] 

96 fields = read_only_fields + ["email", "password", "primary_color", "phone_number", "onboarding_needed"] 

97 extra_kwargs = {"password": {"write_only": True, "required": False}, "email": {"required": False}} 

98 

99 def validate_password(self, value): 

100 validate_password(value) 

101 return value 

102 

103 def create(self, validated_data): 

104 user = self.Meta.model.objects.create_user(**validated_data) 

105 return user 

106 

107 def get_google_account(self, obj): 

108 if getattr(obj, "googleaccount", None): 

109 return True 

110 else: 

111 return False 

112 

113 

114class ResetPasswordSerializer(serializers.Serializer): 

115 email = serializers.EmailField() 

116 

117 def validate_email(self, value): 

118 try: 

119 return User.objects.get(email=value) 

120 except User.DoesNotExist: 

121 raise serializers.ValidationError("No existe un usuario con ese email") 

122 

123 def save(self, validated_data): 

124 email = validated_data.get("email") 

125 user = User.objects.get(email=email) 

126 token = PasswordResetTokenGenerator().make_token(user) 

127 

128 return f"{settings.FRONTEND_DOMAIN}{settings.FRONTEND_RESET_PASSWORD_PATH}/{token}?u={user.pk}", user 

129 

130 

131class SetPasswordSerializer(serializers.Serializer): 

132 """Serializer to set password""" 

133 

134 user_id = serializers.CharField() 

135 token = serializers.CharField() 

136 password = serializers.CharField() 

137 

138 def validate_password(self, value): 

139 validate_password(value) 

140 return value 

141 

142 def validate(self, attrs): 

143 token = attrs.get("token") 

144 user_id = attrs.get("user_id") 

145 try: 

146 user = User.objects.get(pk=user_id) 

147 except User.DoesNotExist: 

148 raise ValidationError({"user": "The user does not exist"}) 

149 

150 verified_token = PasswordResetTokenGenerator().check_token(user, token) 

151 if verified_token: 

152 return attrs 

153 else: 

154 raise ValidationError({"token": "The token is not valid"}) 

155 

156 def save(self, validated_data): 

157 data = validated_data 

158 user_id = data.get("user_id") 

159 user = User.objects.get(pk=user_id) 

160 user.set_password(data.get("password")) 

161 user.save() 

162 

163 

164from django.contrib.auth import get_user_model 

165UserModel = get_user_model() 

166 

167class MyUserDetailsSerializer(UserDetailsSerializer): 

168 practitioner = PractitionerSerializer(read_only=True) 

169 affiliations = AffiliationSerializerForUser(many=True, read_only=True) 

170 google_account = serializers.SerializerMethodField() 

171 class Meta: 

172 extra_fields = [ 

173 'primary_color', 'phone_number', 'onboarding_needed', 'email', 

174 'practitioner', 'affiliations', 'google_account', 

175 

176 ] 

177 # see https://github.com/iMerica/dj-rest-auth/issues/181 

178 # UserModel.XYZ causing attribute error while importing other 

179 # classes from `serializers.py`. So, we need to check whether the auth model has 

180 # the attribute or not 

181 if hasattr(UserModel, 'USERNAME_FIELD'): 181 ↛ 183line 181 didn't jump to line 183, because the condition on line 181 was never false

182 extra_fields.append(UserModel.USERNAME_FIELD) 

183 if hasattr(UserModel, 'EMAIL_FIELD'): 183 ↛ 184line 183 didn't jump to line 184, because the condition on line 183 was never true

184 extra_fields.append(UserModel.EMAIL_FIELD) 

185 if hasattr(UserModel, 'first_name'): 185 ↛ 186line 185 didn't jump to line 186, because the condition on line 185 was never true

186 extra_fields.append('first_name') 

187 if hasattr(UserModel, 'last_name'): 187 ↛ 188line 187 didn't jump to line 188, because the condition on line 187 was never true

188 extra_fields.append('last_name') 

189 model = UserModel 

190 fields = ('pk', *extra_fields) 

191 read_only_fields = ('email',) 

192 

193 def get_google_account(self, obj): 

194 if getattr(obj, 'googleaccount', None): 

195 return True 

196 else: 

197 return False