1
1
import django .contrib .auth .password_validation
2
2
import django .core .exceptions
3
3
import django .core .validators
4
+ import django .db .models
5
+ import pycountry
4
6
import rest_framework .exceptions
5
7
import rest_framework .serializers
6
- import rest_framework .status
7
8
import rest_framework_simplejwt .serializers
8
9
import rest_framework_simplejwt .token_blacklist .models as tb_models
9
10
import rest_framework_simplejwt .tokens
10
11
12
+ import user .constants
11
13
import user .models as user_models
12
14
import user .validators
13
15
14
16
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
+
15
42
class SignUpSerializer (rest_framework .serializers .ModelSerializer ):
16
43
password = rest_framework .serializers .CharField (
17
44
write_only = True ,
18
45
required = True ,
19
46
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 ,
22
49
style = {'input_type' : 'password' },
23
50
)
24
51
name = rest_framework .serializers .CharField (
25
52
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 ,
28
55
)
29
56
surname = rest_framework .serializers .CharField (
30
57
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 ,
33
60
)
34
61
email = rest_framework .serializers .EmailField (
35
62
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 ,
38
65
validators = [
39
66
user .validators .UniqueEmailValidator (
40
67
'This email address is already registered.' ,
@@ -44,15 +71,12 @@ class SignUpSerializer(rest_framework.serializers.ModelSerializer):
44
71
)
45
72
avatar_url = rest_framework .serializers .CharField (
46
73
required = False ,
47
- max_length = 350 ,
74
+ max_length = user . constants . AVATAR_URL_MAX_LENGTH ,
48
75
validators = [
49
76
django .core .validators .URLValidator (schemes = ['http' , 'https' ]),
50
77
],
51
78
)
52
- other = rest_framework .serializers .JSONField (
53
- required = True ,
54
- validators = [user .validators .OtherFieldValidator ()],
55
- )
79
+ other = OtherFieldSerializer (required = True )
56
80
57
81
class Meta :
58
82
model = user_models .User
@@ -94,13 +118,14 @@ class SignInSerializer(
94
118
def validate (self , attrs ):
95
119
user = self .authenticate_user (attrs )
96
120
97
- self .update_token_version (user )
121
+ user .token_version = django .db .models .F ('token_version' ) + 1
122
+ user .save (update_fields = ['token_version' ])
98
123
99
124
data = super ().validate (attrs )
100
125
101
126
refresh = rest_framework_simplejwt .tokens .RefreshToken (data ['refresh' ])
102
127
103
- self .invalidate_previous_tokens (user , refresh ['jti' ])
128
+ self .blacklist_other_tokens (user , refresh ['jti' ])
104
129
105
130
return data
106
131
@@ -128,19 +153,18 @@ def authenticate_user(self, attrs):
128
153
129
154
return user
130
155
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
+ )
142
165
143
- def get_token (self , user ):
166
+ @classmethod
167
+ def get_token (cls , user ):
144
168
token = super ().get_token (user )
145
169
token ['token_version' ] = user .token_version
146
170
return token
0 commit comments