Issues (463)

djoser/serializers.py (1 issue)

Severity
1
from django.contrib.auth import authenticate, get_user_model
2
from django.contrib.auth.password_validation import validate_password
3
from django.core import exceptions as django_exceptions
4
from django.db import IntegrityError, transaction
5
from rest_framework import exceptions, serializers
6
from rest_framework.exceptions import ValidationError
7
from rest_framework.settings import api_settings
8
9
from djoser import utils
10
from djoser.compat import get_user_email, get_user_email_field_name
11
from djoser.conf import settings
12
13
User = get_user_model()
14
15
16
class UserSerializer(serializers.ModelSerializer):
17
    class Meta:
18
        model = User
19
        fields = tuple(User.REQUIRED_FIELDS) + (
20
            settings.USER_ID_FIELD,
21
            settings.LOGIN_FIELD,
22
        )
23
        read_only_fields = (settings.LOGIN_FIELD,)
24
25
    def update(self, instance, validated_data):
26
        email_field = get_user_email_field_name(User)
27
        if settings.SEND_ACTIVATION_EMAIL and email_field in validated_data:
28
            instance_email = get_user_email(instance)
29
            if instance_email != validated_data[email_field]:
30
                instance.is_active = False
31
                instance.save(update_fields=["is_active"])
32
        return super().update(instance, validated_data)
33
34
35
class UserCreateSerializer(serializers.ModelSerializer):
36
    password = serializers.CharField(style={"input_type": "password"}, write_only=True)
37
38
    default_error_messages = {
39
        "cannot_create_user": settings.CONSTANTS.messages.CANNOT_CREATE_USER_ERROR
40
    }
41
42
    class Meta:
43
        model = User
44
        fields = tuple(User.REQUIRED_FIELDS) + (
45
            settings.LOGIN_FIELD,
46
            settings.USER_ID_FIELD,
47
            "password",
48
        )
49
50
    def validate(self, attrs):
51
        user = User(**attrs)
52
        password = attrs.get("password")
53
54
        try:
55
            validate_password(password, user)
56
        except django_exceptions.ValidationError as e:
57
            serializer_error = serializers.as_serializer_error(e)
58
            raise serializers.ValidationError(
59
                {"password": serializer_error[api_settings.NON_FIELD_ERRORS_KEY]}
60
            )
61
62
        return attrs
63
64
    def create(self, validated_data):
65
        try:
66
            user = self.perform_create(validated_data)
67
        except IntegrityError:
68
            self.fail("cannot_create_user")
69
70
        return user
71
72
    def perform_create(self, validated_data):
73
        with transaction.atomic():
74
            user = User.objects.create_user(**validated_data)
75
            if settings.SEND_ACTIVATION_EMAIL:
76
                user.is_active = False
77
                user.save(update_fields=["is_active"])
78
        return user
79
80
81
class UserCreatePasswordRetypeSerializer(UserCreateSerializer):
82
    default_error_messages = {
83
        "password_mismatch": settings.CONSTANTS.messages.PASSWORD_MISMATCH_ERROR
84
    }
85
86
    def __init__(self, *args, **kwargs):
87
        super().__init__(*args, **kwargs)
88
        self.fields["re_password"] = serializers.CharField(
89
            style={"input_type": "password"}
90
        )
91
92
    def validate(self, attrs):
93
        self.fields.pop("re_password", None)
94
        re_password = attrs.pop("re_password")
95
        attrs = super().validate(attrs)
96
        if attrs["password"] == re_password:
97
            return attrs
98
        else:
99
            self.fail("password_mismatch")
100
101
102
class TokenCreateSerializer(serializers.Serializer):
103
    password = serializers.CharField(required=False, style={"input_type": "password"})
104
105
    default_error_messages = {
106
        "invalid_credentials": settings.CONSTANTS.messages.INVALID_CREDENTIALS_ERROR,
107
        "inactive_account": settings.CONSTANTS.messages.INACTIVE_ACCOUNT_ERROR,
108
    }
109
110
    def __init__(self, *args, **kwargs):
111
        super().__init__(*args, **kwargs)
112
        self.user = None
113
        self.fields[settings.LOGIN_FIELD] = serializers.CharField(required=False)
114
115
    def validate(self, attrs):
116
        password = attrs.get("password")
117
        params = {settings.LOGIN_FIELD: attrs.get(settings.LOGIN_FIELD)}
118
        self.user = authenticate(
119
            request=self.context.get("request"), **params, password=password
0 ignored issues
show
invalid syntax (<string>, line 119)
Loading history...
120
        )
121
        if not self.user:
122
            self.user = User.objects.filter(**params).first()
123
            if self.user and not self.user.check_password(password):
124
                self.fail("invalid_credentials")
125
        if self.user and self.user.is_active:
126
            return attrs
127
        self.fail("invalid_credentials")
128
129
130
class UserFunctionsMixin:
131
    def get_user(self, is_active=True):
132
        try:
133
            user = User._default_manager.get(
134
                is_active=is_active,
135
                **{self.email_field: self.data.get(self.email_field, "")},
136
            )
137
            if user.has_usable_password():
138
                return user
139
        except User.DoesNotExist:
140
            pass
141
        if (
142
            settings.PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND
143
            or settings.USERNAME_RESET_SHOW_EMAIL_NOT_FOUND
144
        ):
145
            self.fail("email_not_found")
146
147
148
class SendEmailResetSerializer(serializers.Serializer, UserFunctionsMixin):
149
    default_error_messages = {
150
        "email_not_found": settings.CONSTANTS.messages.EMAIL_NOT_FOUND
151
    }
152
153
    def __init__(self, *args, **kwargs):
154
        super().__init__(*args, **kwargs)
155
156
        self.email_field = get_user_email_field_name(User)
157
        self.fields[self.email_field] = serializers.EmailField()
158
159
160
class UidAndTokenSerializer(serializers.Serializer):
161
    uid = serializers.CharField()
162
    token = serializers.CharField()
163
164
    default_error_messages = {
165
        "invalid_token": settings.CONSTANTS.messages.INVALID_TOKEN_ERROR,
166
        "invalid_uid": settings.CONSTANTS.messages.INVALID_UID_ERROR,
167
    }
168
169
    def validate(self, attrs):
170
        validated_data = super().validate(attrs)
171
172
        # uid validation have to be here, because validate_<field_name>
173
        # doesn't work with modelserializer
174
        try:
175
            uid = utils.decode_uid(self.initial_data.get("uid", ""))
176
            self.user = User.objects.get(pk=uid)
177
        except (User.DoesNotExist, ValueError, TypeError, OverflowError):
178
            key_error = "invalid_uid"
179
            raise ValidationError(
180
                {"uid": [self.error_messages[key_error]]}, code=key_error
181
            )
182
183
        is_token_valid = self.context["view"].token_generator.check_token(
184
            self.user, self.initial_data.get("token", "")
185
        )
186
        if is_token_valid:
187
            return validated_data
188
        else:
189
            key_error = "invalid_token"
190
            raise ValidationError(
191
                {"token": [self.error_messages[key_error]]}, code=key_error
192
            )
193
194
195
class ActivationSerializer(UidAndTokenSerializer):
196
    default_error_messages = {
197
        "stale_token": settings.CONSTANTS.messages.STALE_TOKEN_ERROR
198
    }
199
200
    def validate(self, attrs):
201
        attrs = super().validate(attrs)
202
        if not self.user.is_active:
203
            return attrs
204
        raise exceptions.PermissionDenied(self.error_messages["stale_token"])
205
206
207
class PasswordSerializer(serializers.Serializer):
208
    new_password = serializers.CharField(style={"input_type": "password"})
209
210
    def validate(self, attrs):
211
        user = self.context["request"].user or self.user
212
        # why assert? There are ValidationError / fail everywhere
213
        assert user is not None
214
215
        try:
216
            validate_password(attrs["new_password"], user)
217
        except django_exceptions.ValidationError as e:
218
            raise serializers.ValidationError({"new_password": list(e.messages)})
219
        return super().validate(attrs)
220
221
222
class PasswordRetypeSerializer(PasswordSerializer):
223
    re_new_password = serializers.CharField(style={"input_type": "password"})
224
225
    default_error_messages = {
226
        "password_mismatch": settings.CONSTANTS.messages.PASSWORD_MISMATCH_ERROR
227
    }
228
229
    def validate(self, attrs):
230
        attrs = super().validate(attrs)
231
        if attrs["new_password"] == attrs["re_new_password"]:
232
            return attrs
233
        else:
234
            self.fail("password_mismatch")
235
236
237
class CurrentPasswordSerializer(serializers.Serializer):
238
    current_password = serializers.CharField(style={"input_type": "password"})
239
240
    default_error_messages = {
241
        "invalid_password": settings.CONSTANTS.messages.INVALID_PASSWORD_ERROR
242
    }
243
244
    def validate_current_password(self, value):
245
        is_password_valid = self.context["request"].user.check_password(value)
246
        if is_password_valid:
247
            return value
248
        else:
249
            self.fail("invalid_password")
250
251
252
class UsernameSerializer(serializers.ModelSerializer):
253
    class Meta:
254
        model = User
255
        fields = (settings.LOGIN_FIELD,)
256
257
    def __init__(self, *args, **kwargs):
258
        super().__init__(*args, **kwargs)
259
        self.username_field = settings.LOGIN_FIELD
260
        self._default_username_field = User.USERNAME_FIELD
261
        self.fields["new_{}".format(self.username_field)] = self.fields.pop(
262
            self.username_field
263
        )
264
265
    def save(self, **kwargs):
266
        if self.username_field != self._default_username_field:
267
            kwargs[User.USERNAME_FIELD] = self.validated_data.get(
268
                "new_{}".format(self.username_field)
269
            )
270
        return super().save(**kwargs)
271
272
273
class UsernameRetypeSerializer(UsernameSerializer):
274
    default_error_messages = {
275
        "username_mismatch": settings.CONSTANTS.messages.USERNAME_MISMATCH_ERROR.format(
276
            settings.LOGIN_FIELD
277
        )
278
    }
279
280
    def __init__(self, *args, **kwargs):
281
        super().__init__(*args, **kwargs)
282
        self.fields["re_new_" + settings.LOGIN_FIELD] = serializers.CharField()
283
284
    def validate(self, attrs):
285
        attrs = super().validate(attrs)
286
        new_username = attrs[settings.LOGIN_FIELD]
287
        if new_username != attrs["re_new_{}".format(settings.LOGIN_FIELD)]:
288
            self.fail("username_mismatch")
289
        else:
290
            return attrs
291
292
293
class TokenSerializer(serializers.ModelSerializer):
294
    auth_token = serializers.CharField(source="key")
295
296
    class Meta:
297
        model = settings.TOKEN_MODEL
298
        fields = ("auth_token",)
299
300
301
class SetPasswordSerializer(PasswordSerializer, CurrentPasswordSerializer):
302
    pass
303
304
305
class SetPasswordRetypeSerializer(PasswordRetypeSerializer, CurrentPasswordSerializer):
306
    pass
307
308
309
class PasswordResetConfirmSerializer(UidAndTokenSerializer, PasswordSerializer):
310
    pass
311
312
313
class PasswordResetConfirmRetypeSerializer(
314
    UidAndTokenSerializer, PasswordRetypeSerializer
315
):
316
    pass
317
318
319
class UsernameResetConfirmSerializer(UidAndTokenSerializer, UsernameSerializer):
320
    pass
321
322
323
class UsernameResetConfirmRetypeSerializer(
324
    UidAndTokenSerializer, UsernameRetypeSerializer
325
):
326
    pass
327
328
329
class UserDeleteSerializer(CurrentPasswordSerializer):
330
    pass
331
332
333
class SetUsernameSerializer(UsernameSerializer, CurrentPasswordSerializer):
334
    class Meta:
335
        model = User
336
        fields = (settings.LOGIN_FIELD, "current_password")
337
338
339
class SetUsernameRetypeSerializer(SetUsernameSerializer, UsernameRetypeSerializer):
340
    pass
341