Files
igny8/backend/igny8_core/plugins/serializers.py
2026-01-09 21:38:14 +00:00

239 lines
7.4 KiB
Python

"""
Plugin Distribution System Serializers
"""
from rest_framework import serializers
from .models import Plugin, PluginVersion, PluginInstallation, PluginDownload
class PluginVersionSerializer(serializers.ModelSerializer):
"""Serializer for plugin versions."""
download_count = serializers.SerializerMethodField()
class Meta:
model = PluginVersion
fields = [
'id',
'version',
'version_code',
'status',
'file_size',
'checksum',
'changelog',
'min_api_version',
'min_platform_version',
'min_php_version',
'force_update',
'released_at',
'created_at',
'download_count',
]
read_only_fields = ['id', 'version_code', 'created_at', 'download_count']
def get_download_count(self, obj):
return obj.get_download_count()
class PluginSerializer(serializers.ModelSerializer):
"""Serializer for plugins."""
latest_version = serializers.SerializerMethodField()
download_count = serializers.SerializerMethodField()
class Meta:
model = Plugin
fields = [
'id',
'name',
'slug',
'platform',
'description',
'homepage_url',
'is_active',
'latest_version',
'download_count',
'created_at',
'updated_at',
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_latest_version(self, obj):
latest = obj.get_latest_version()
if latest:
return {
'version': latest.version,
'version_code': latest.version_code,
'released_at': latest.released_at,
'changelog': latest.changelog,
}
return None
def get_download_count(self, obj):
return obj.get_download_count()
class PluginDetailSerializer(PluginSerializer):
"""Detailed serializer for plugins including versions."""
versions = PluginVersionSerializer(many=True, read_only=True)
class Meta(PluginSerializer.Meta):
fields = PluginSerializer.Meta.fields + ['versions']
class PluginInfoSerializer(serializers.Serializer):
"""
Serializer for WordPress plugin info endpoint.
Returns data in WordPress-compatible format.
"""
name = serializers.CharField()
slug = serializers.CharField()
version = serializers.CharField()
author = serializers.CharField(default='IGNY8')
homepage = serializers.URLField()
description = serializers.CharField()
changelog = serializers.CharField()
download_url = serializers.URLField()
file_size = serializers.IntegerField()
requires_php = serializers.CharField()
tested_wp = serializers.CharField(default='6.7')
class CheckUpdateSerializer(serializers.Serializer):
"""Serializer for update check response."""
update_available = serializers.BooleanField()
current_version = serializers.CharField()
latest_version = serializers.CharField(allow_null=True)
latest_version_code = serializers.IntegerField(allow_null=True)
download_url = serializers.URLField(allow_null=True)
changelog = serializers.CharField(allow_null=True)
info_url = serializers.URLField(allow_null=True)
force_update = serializers.BooleanField(default=False)
checksum = serializers.CharField(allow_null=True)
class RegisterInstallationSerializer(serializers.Serializer):
"""Serializer for registering plugin installations."""
site_id = serializers.IntegerField()
version = serializers.CharField()
def validate_site_id(self, value):
from igny8_core.auth.models import Site
try:
Site.objects.get(id=value)
except Site.DoesNotExist:
raise serializers.ValidationError("Site not found")
return value
class HealthCheckSerializer(serializers.Serializer):
"""Serializer for plugin health check."""
site_id = serializers.IntegerField()
version = serializers.CharField()
status = serializers.ChoiceField(choices=['active', 'inactive', 'error'])
error_message = serializers.CharField(required=False, allow_blank=True)
class PluginInstallationSerializer(serializers.ModelSerializer):
"""Serializer for plugin installations."""
plugin_name = serializers.CharField(source='plugin.name', read_only=True)
plugin_slug = serializers.CharField(source='plugin.slug', read_only=True)
current_version_str = serializers.CharField(source='current_version.version', read_only=True)
site_name = serializers.CharField(source='site.name', read_only=True)
pending_update_version = serializers.SerializerMethodField()
class Meta:
model = PluginInstallation
fields = [
'id',
'site',
'site_name',
'plugin',
'plugin_name',
'plugin_slug',
'current_version',
'current_version_str',
'is_active',
'last_health_check',
'health_status',
'pending_update',
'pending_update_version',
'update_notified_at',
'created_at',
'updated_at',
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_pending_update_version(self, obj):
if obj.pending_update:
return obj.pending_update.version
return None
class PluginDownloadSerializer(serializers.ModelSerializer):
"""Serializer for plugin downloads."""
plugin_name = serializers.CharField(source='plugin.name', read_only=True)
version_str = serializers.CharField(source='version.version', read_only=True)
class Meta:
model = PluginDownload
fields = [
'id',
'plugin',
'plugin_name',
'version',
'version_str',
'site',
'account',
'download_type',
'created_at',
]
read_only_fields = ['id', 'created_at']
# Admin Serializers
class AdminPluginVersionCreateSerializer(serializers.ModelSerializer):
"""Serializer for creating new plugin versions (admin)."""
class Meta:
model = PluginVersion
fields = [
'version',
'status',
'changelog',
'min_api_version',
'min_platform_version',
'min_php_version',
'force_update',
]
def validate_version(self, value):
"""Ensure version follows semantic versioning."""
import re
if not re.match(r'^\d+\.\d+\.\d+$', value):
raise serializers.ValidationError(
"Version must follow semantic versioning (e.g., 1.0.0)"
)
return value
class AdminPluginVersionUploadSerializer(serializers.Serializer):
"""Serializer for uploading plugin ZIP file."""
file = serializers.FileField()
def validate_file(self, value):
"""Ensure uploaded file is a ZIP."""
if not value.name.endswith('.zip'):
raise serializers.ValidationError("File must be a ZIP archive")
# Check file size (max 50MB)
max_size = 50 * 1024 * 1024
if value.size > max_size:
raise serializers.ValidationError(
f"File too large. Maximum size is {max_size / 1024 / 1024}MB"
)
return value