from pathlib import Path from django.contrib.auth.password_validation import validate_password from django.core import signing from rest_framework import serializers from apps.library.services import MEDIA_FILE_SALT, VIDEO_EXTENSIONS from .models import User def signed_media_url(request, item): """A signed media URL an tag can load for an authenticated user.""" if item is None: return None user = getattr(request, "user", None) if user is None or not getattr(user, "is_authenticated", False): return None location = item.locations.first() is_video = ( location is not None and Path(location.rel_path).suffix.lower() in VIDEO_EXTENSIONS ) action = "thumbnail" if is_video else "raw" signature = signing.dumps( {"item": item.id, "user": user.id, "action": action}, salt=MEDIA_FILE_SALT, ) return f"/api/files/J-{item.id}/{action}/?sig={signature}" class UserSerializer(serializers.ModelSerializer): e621_configured = serializers.BooleanField(read_only=True) can_upload = serializers.BooleanField(read_only=True) avatar_j_id = serializers.SerializerMethodField() avatar_url = serializers.SerializerMethodField() class Meta: model = User fields = [ "id", "username", "email", "is_staff", "is_superuser", "date_joined", "role", "can_upload", "avatar_j_id", "avatar_url", "e621_username", "e621_configured", ] read_only_fields = fields def get_avatar_j_id(self, obj): return f"J-{obj.avatar_id}" if obj.avatar_id else None def get_avatar_url(self, obj): return signed_media_url(self.context.get("request"), obj.avatar) class UserListSerializer(serializers.ModelSerializer): avatar_j_id = serializers.SerializerMethodField() avatar_url = serializers.SerializerMethodField() uploads_count = serializers.IntegerField(read_only=True) class Meta: model = User fields = [ "id", "username", "email", "role", "is_staff", "is_superuser", "date_joined", "avatar_j_id", "avatar_url", "uploads_count", ] read_only_fields = fields def get_avatar_j_id(self, obj): return f"J-{obj.avatar_id}" if obj.avatar_id else None def get_avatar_url(self, obj): return signed_media_url(self.context.get("request"), obj.avatar) class UserUpdateSerializer(serializers.Serializer): avatar_j_id = serializers.CharField( required=False, allow_blank=True, allow_null=True ) role = serializers.ChoiceField(choices=User.ROLE_CHOICES, required=False) class RegisterSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True, validators=[validate_password]) class Meta: model = User fields = ["username", "email", "password"] def create(self, validated_data): return User.objects.create_user(**validated_data) class E621CredentialsSerializer(serializers.Serializer): username = serializers.CharField(max_length=100, allow_blank=True) api_key = serializers.CharField( max_length=100, allow_blank=True, trim_whitespace=True ) base_url = serializers.URLField( max_length=200, required=False, allow_blank=True )