185 lines
5.8 KiB
Python
185 lines
5.8 KiB
Python
from django.contrib.auth import get_user_model
|
|
from rest_framework import serializers
|
|
|
|
from apps.accounts.models import ApiKey
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class PkAsIdMixin(serializers.Serializer):
|
|
"""Keep JSON `id` stable after ERD-named primary keys."""
|
|
|
|
id = serializers.IntegerField(source="pk", read_only=True)
|
|
|
|
|
|
class UserSerializer(PkAsIdMixin, serializers.ModelSerializer):
|
|
managed_by = serializers.PrimaryKeyRelatedField(
|
|
queryset=User.objects.filter(status__in=["buh", "bu_admin"]),
|
|
allow_null=True,
|
|
required=False,
|
|
)
|
|
managed_by_name = serializers.CharField(
|
|
source="managed_by.user_name", read_only=True, allow_null=True
|
|
)
|
|
managed_by_pending = serializers.PrimaryKeyRelatedField(read_only=True)
|
|
managed_by_pending_name = serializers.CharField(
|
|
source="managed_by_pending.user_name", read_only=True, allow_null=True
|
|
)
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = [
|
|
"id",
|
|
"user_name",
|
|
"status",
|
|
"is_superuser",
|
|
"managed_by",
|
|
"managed_by_name",
|
|
"managed_by_pending",
|
|
"managed_by_pending_name",
|
|
"managed_by_requested_at",
|
|
"created_at",
|
|
"updated_at",
|
|
]
|
|
read_only_fields = [
|
|
"id",
|
|
"is_superuser",
|
|
"managed_by_name",
|
|
"managed_by_pending",
|
|
"managed_by_pending_name",
|
|
"managed_by_requested_at",
|
|
"created_at",
|
|
"updated_at",
|
|
]
|
|
|
|
|
|
class UserWriteSerializer(PkAsIdMixin, serializers.ModelSerializer):
|
|
"""Create/update users for Account Admin. Password required on create."""
|
|
|
|
password = serializers.CharField(write_only=True, required=False, allow_blank=False)
|
|
managed_by = serializers.PrimaryKeyRelatedField(
|
|
queryset=User.objects.filter(status__in=["buh", "bu_admin"]),
|
|
allow_null=True,
|
|
required=False,
|
|
)
|
|
managed_by_name = serializers.CharField(
|
|
source="managed_by.user_name", read_only=True, allow_null=True
|
|
)
|
|
managed_by_pending = serializers.PrimaryKeyRelatedField(read_only=True)
|
|
managed_by_pending_name = serializers.CharField(
|
|
source="managed_by_pending.user_name", read_only=True, allow_null=True
|
|
)
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = [
|
|
"id",
|
|
"user_name",
|
|
"status",
|
|
"is_superuser",
|
|
"password",
|
|
"managed_by",
|
|
"managed_by_name",
|
|
"managed_by_pending",
|
|
"managed_by_pending_name",
|
|
"managed_by_requested_at",
|
|
"created_at",
|
|
"updated_at",
|
|
]
|
|
read_only_fields = [
|
|
"id",
|
|
"is_superuser",
|
|
"managed_by_name",
|
|
"managed_by_pending",
|
|
"managed_by_pending_name",
|
|
"managed_by_requested_at",
|
|
"created_at",
|
|
"updated_at",
|
|
]
|
|
|
|
def validate_password(self, value: str) -> str:
|
|
if value is not None and not str(value).strip():
|
|
raise serializers.ValidationError("Password cannot be blank.")
|
|
return value
|
|
|
|
def validate(self, attrs):
|
|
if self.instance is None and not attrs.get("password"):
|
|
raise serializers.ValidationError({"password": "This field is required."})
|
|
|
|
new_status = attrs.get("status")
|
|
if new_status == User.STATUS_SUPERUSER:
|
|
raise serializers.ValidationError(
|
|
{"status": "Superuser accounts cannot be created or assigned here."}
|
|
)
|
|
|
|
request = self.context.get("request")
|
|
actor = getattr(request, "user", None) if request else None
|
|
instance = self.instance
|
|
if (
|
|
instance is not None
|
|
and actor is not None
|
|
and getattr(actor, "is_authenticated", False)
|
|
and instance.pk == actor.pk
|
|
and "status" in attrs
|
|
and attrs["status"] != instance.status
|
|
):
|
|
if attrs["status"] == User.STATUS_INACTIVE:
|
|
raise serializers.ValidationError(
|
|
{"status": "You cannot deactivate your own account."}
|
|
)
|
|
raise serializers.ValidationError(
|
|
{"status": "You cannot change your own account status."}
|
|
)
|
|
return attrs
|
|
|
|
def create(self, validated_data):
|
|
password = validated_data.pop("password")
|
|
user_name = validated_data.pop("user_name")
|
|
return User.objects.create_user(
|
|
user_name=user_name, password=password, **validated_data
|
|
)
|
|
|
|
def update(self, instance, validated_data):
|
|
password = validated_data.pop("password", None)
|
|
for attr, value in validated_data.items():
|
|
setattr(instance, attr, value)
|
|
if password:
|
|
instance.set_password(password)
|
|
instance.save()
|
|
return instance
|
|
|
|
|
|
class SetPasswordSerializer(serializers.Serializer):
|
|
password = serializers.CharField(write_only=True, allow_blank=False)
|
|
|
|
def validate_password(self, value: str) -> str:
|
|
if not str(value).strip():
|
|
raise serializers.ValidationError("Password cannot be blank.")
|
|
return value
|
|
|
|
|
|
class LoginSerializer(serializers.Serializer):
|
|
user_name = serializers.CharField(max_length=30)
|
|
password = serializers.CharField(write_only=True)
|
|
|
|
|
|
class ApiKeySerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = ApiKey
|
|
fields = [
|
|
"id",
|
|
"name",
|
|
"prefix",
|
|
"is_active",
|
|
"last_used_at",
|
|
"created_at",
|
|
"updated_at",
|
|
"user",
|
|
]
|
|
read_only_fields = fields
|
|
|
|
|
|
class ApiKeyCreateSerializer(serializers.Serializer):
|
|
name = serializers.CharField(max_length=100)
|
|
user_id = serializers.IntegerField(required=False)
|