11import django .contrib .auth .password_validation
22import django .core .exceptions
33import django .core .validators
4+ import django .db .models
5+ import pycountry
46import rest_framework .exceptions
57import rest_framework .serializers
6- import rest_framework .status
78import rest_framework_simplejwt .serializers
89import rest_framework_simplejwt .token_blacklist .models as tb_models
910import rest_framework_simplejwt .tokens
1011
12+ import user .constants
1113import user .models as user_models
1214import user .validators
1315
1416
17+ class OtherFieldSerializer (rest_framework .serializers .Serializer ):
18+ age = rest_framework .serializers .IntegerField (
19+ required = True ,
20+ min_value = user .constants .AGE_MIN ,
21+ max_value = user .constants .AGE_MAX ,
22+ )
23+ country = rest_framework .serializers .CharField (
24+ required = True ,
25+ max_length = user .constants .COUNTRY_CODE_LENGTH ,
26+ min_length = user .constants .COUNTRY_CODE_LENGTH ,
27+ )
28+
29+ def validate (self , value ):
30+ country = value ['country' ].upper ()
31+
32+ try :
33+ pycountry .countries .lookup (country )
34+ except LookupError :
35+ raise rest_framework .serializers .ValidationError (
36+ 'Invalid ISO 3166-1 alpha-2 country code.' ,
37+ )
38+
39+ return value
40+
41+
1542class SignUpSerializer (rest_framework .serializers .ModelSerializer ):
1643 password = rest_framework .serializers .CharField (
1744 write_only = True ,
1845 required = True ,
1946 validators = [django .contrib .auth .password_validation .validate_password ],
20- max_length = 60 ,
21- min_length = 8 ,
47+ max_length = user . constants . PASSWORD_MAX_LENGTH ,
48+ min_length = user . constants . PASSWORD_MIN_LENGTH ,
2249 style = {'input_type' : 'password' },
2350 )
2451 name = rest_framework .serializers .CharField (
2552 required = True ,
26- min_length = 1 ,
27- max_length = 100 ,
53+ min_length = user . constants . NAME_MIN_LENGTH ,
54+ max_length = user . constants . NAME_MAX_LENGTH ,
2855 )
2956 surname = rest_framework .serializers .CharField (
3057 required = True ,
31- min_length = 1 ,
32- max_length = 120 ,
58+ min_length = user . constants . SURNAME_MIN_LENGTH ,
59+ max_length = user . constants . SURNAME_MAX_LENGTH ,
3360 )
3461 email = rest_framework .serializers .EmailField (
3562 required = True ,
36- min_length = 8 ,
37- max_length = 120 ,
63+ min_length = user . constants . EMAIL_MIN_LENGTH ,
64+ max_length = user . constants . EMAIL_MAX_LENGTH ,
3865 validators = [
3966 user .validators .UniqueEmailValidator (
4067 'This email address is already registered.' ,
@@ -44,15 +71,12 @@ class SignUpSerializer(rest_framework.serializers.ModelSerializer):
4471 )
4572 avatar_url = rest_framework .serializers .CharField (
4673 required = False ,
47- max_length = 350 ,
74+ max_length = user . constants . AVATAR_URL_MAX_LENGTH ,
4875 validators = [
4976 django .core .validators .URLValidator (schemes = ['http' , 'https' ]),
5077 ],
5178 )
52- other = rest_framework .serializers .JSONField (
53- required = True ,
54- validators = [user .validators .OtherFieldValidator ()],
55- )
79+ other = OtherFieldSerializer (required = True )
5680
5781 class Meta :
5882 model = user_models .User
@@ -94,13 +118,14 @@ class SignInSerializer(
94118 def validate (self , attrs ):
95119 user = self .authenticate_user (attrs )
96120
97- self .update_token_version (user )
121+ user .token_version = django .db .models .F ('token_version' ) + 1
122+ user .save (update_fields = ['token_version' ])
98123
99124 data = super ().validate (attrs )
100125
101126 refresh = rest_framework_simplejwt .tokens .RefreshToken (data ['refresh' ])
102127
103- self .invalidate_previous_tokens (user , refresh ['jti' ])
128+ self .blacklist_other_tokens (user , refresh ['jti' ])
104129
105130 return data
106131
@@ -128,19 +153,18 @@ def authenticate_user(self, attrs):
128153
129154 return user
130155
131- def invalidate_previous_tokens (self , user , current_jti ):
132- outstanding_tokens = tb_models .OutstandingToken .objects .filter (
133- user = user ,
134- ).exclude (jti = current_jti )
135-
136- for token in outstanding_tokens :
137- tb_models .BlacklistedToken .objects .get_or_create (token = token )
138-
139- def update_token_version (self , user ):
140- user .token_version += 1
141- user .save ()
156+ def blacklist_other_tokens (self , user , current_jti ):
157+ qs = tb_models .OutstandingToken .objects .filter (user = user ).exclude (
158+ jti = current_jti ,
159+ )
160+ blacklisted = [tb_models .BlacklistedToken (token = tok ) for tok in qs ]
161+ tb_models .BlacklistedToken .objects .bulk_create (
162+ blacklisted ,
163+ ignore_conflicts = True ,
164+ )
142165
143- def get_token (self , user ):
166+ @classmethod
167+ def get_token (cls , user ):
144168 token = super ().get_token (user )
145169 token ['token_version' ] = user .token_version
146170 return token
0 commit comments