from django.contrib.auth.hashers import check_password from django.contrib.auth.models import User from django.core.exceptions import ObjectDoesNotExist from rest_framework.exceptions import ValidationError from core import serializers from users.models import UserInfo from users.services.userinfo import UserStatusService from users.services.validators import timezone_validation, password_validation, validate_expire_date, \ OnlyCharNumericValidator """The presence of 2 duplicate serilizers (UsersListSerializer,UserInfoListSerializer) is made for the quick release of functionality. The reason is hiding the password from the output of the list of users""" class UserSerializers(serializers.ModelSerializer): username = serializers.CharField(), old_password = serializers.CharField(required=False) def to_representation(self, instance): return { 'id': instance.id, 'username': instance.username, 'first_name': instance.first_name, "email": instance.email, 'is_active': instance.is_active } class Meta: model = User fields = ('id', 'username', 'first_name', 'is_active', "password", "email", "old_password") extra_kwargs = { 'username': { 'validators': [], 'max_length': 131 # 150 chars in the model, but after deleting we added 19 chars }, 'first_name': { 'required': True, 'allow_blank': False }, 'email': { 'required': True, 'allow_blank': False } } class UserInfoSerializer(serializers.ModelLocalizedSerializer): user = UserSerializers(required=True, many=False) user_status = serializers.SerializerMethodField() def get_user_status(self, user_info: UserInfo) -> str: return UserStatusService(user_info.user).get_status() def create(self, validated_data): """TODO !!! Important !!!! Until the role model is developed, all created users are admins""" if "password" in validated_data["user"]: from django.contrib.auth.hashers import make_password validated_data["user"]["password"] = make_password(validated_data["user"]["password"]) validated_data["user"]["is_staff"] = True validated_data["user"]["is_superuser"] = True new_user = User.objects.create(**validated_data["user"]) else: new_user = User.objects.create(**validated_data["user"]) user_info = None if new_user: user_info = UserInfo.objects.create(user=new_user, comment=validated_data.get("comment"), timezone=validated_data.get("timezone"), expire_date=validated_data.get('expire_date')) return user_info def validate_user(self, user): username = user['username'] OnlyCharNumericValidator.validate(username) try: user = User.objects.get(username=username) raise ValidationError(f"User {username} already exists") except ObjectDoesNotExist: return user def validate(self, data): timezone_validation(data) password_validation(data) validate_expire_date(data) return data class Meta: model = UserInfo fields = "__all__" class UserInfoUpdateSerializer(serializers.ModelLocalizedSerializer): user = UserSerializers(required=False) def update(self, instance, validated_data): try: users_data = validated_data.pop('user') instance.comment = validated_data.get('comment', instance.comment) instance.timezone = validated_data.get("timezone", instance.timezone) instance.expire_date = validated_data.get("expire_date", instance.expire_date) instance.save() user = instance.user user.username = users_data.get('username', user.username) user.first_name = users_data.get("first_name", user.first_name) user.is_active = users_data.get("is_active", user.is_active) user.email = users_data.get("email", user.email) user.save() if users_data.get("password", None): user.set_password(users_data.get("password")) user.save() except KeyError: instance.comment = validated_data.get('comment', instance.comment) instance.timezone = validated_data.get("timezone", instance.timezone) instance.expire_date = validated_data.get("expire_date", instance.expire_date) instance.save() user = instance.user user.save() return instance def validate(self, data): """validate data""" timezone_validation(data) password_validation(data) validate_expire_date(data) if 'user' not in data: raise ValidationError({'status': 'error', 'detail': "Invalid request format"}) if 'password' in data['user']: if check_password(data['user']['password'], self.instance.user.password): raise ValidationError({'status': 'error', 'detail': 'The password must be different from ' 'the previous one'}) if (self.instance.user == self.context['request'].user and not check_password(data['user'].get('old_password', ''), self.instance.user.password)): raise ValidationError({'status': 'error', 'detail': 'Provide correct old password'}) if 'is_active' in data['user']: if self.context['request'].user == self.instance.user and not data['user']['is_active']: raise ValidationError({'status': 'error', 'detail': "You can't disable your account"}) return data class Meta: model = UserInfo fields = "__all__"