142 lines
5.9 KiB
Python
142 lines
5.9 KiB
Python
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__"
|