199 lines
7.1 KiB
Python
199 lines
7.1 KiB
Python
"""
|
|
Publisher ViewSet
|
|
Phase 5: Sites Renderer & Publishing
|
|
"""
|
|
from rest_framework import status, viewsets
|
|
from rest_framework.decorators import action
|
|
from rest_framework.response import Response
|
|
|
|
from igny8_core.api.base import SiteSectorModelViewSet
|
|
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsEditorOrAbove
|
|
from igny8_core.api.response import success_response, error_response
|
|
from igny8_core.api.throttles import DebugScopedRateThrottle
|
|
from igny8_core.business.publishing.models import PublishingRecord, DeploymentRecord
|
|
from igny8_core.business.publishing.services.publisher_service import PublisherService
|
|
from igny8_core.business.site_building.models import SiteBlueprint
|
|
|
|
|
|
class PublishingRecordViewSet(SiteSectorModelViewSet):
|
|
"""
|
|
ViewSet for PublishingRecord model.
|
|
"""
|
|
queryset = PublishingRecord.objects.select_related('content', 'site_blueprint')
|
|
permission_classes = [IsAuthenticatedAndActive, IsEditorOrAbove]
|
|
throttle_scope = 'publisher'
|
|
throttle_classes = [DebugScopedRateThrottle]
|
|
|
|
def get_serializer_class(self):
|
|
# Will be created in next step
|
|
from rest_framework import serializers
|
|
|
|
class PublishingRecordSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = PublishingRecord
|
|
fields = '__all__'
|
|
|
|
return PublishingRecordSerializer
|
|
|
|
|
|
class DeploymentRecordViewSet(SiteSectorModelViewSet):
|
|
"""
|
|
ViewSet for DeploymentRecord model.
|
|
"""
|
|
queryset = DeploymentRecord.objects.select_related('site_blueprint')
|
|
permission_classes = [IsAuthenticatedAndActive, IsEditorOrAbove]
|
|
throttle_scope = 'publisher'
|
|
throttle_classes = [DebugScopedRateThrottle]
|
|
|
|
def get_serializer_class(self):
|
|
# Will be created in next step
|
|
from rest_framework import serializers
|
|
|
|
class DeploymentRecordSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = DeploymentRecord
|
|
fields = '__all__'
|
|
|
|
return DeploymentRecordSerializer
|
|
|
|
|
|
class PublisherViewSet(viewsets.ViewSet):
|
|
"""
|
|
Publisher actions for publishing content and sites.
|
|
"""
|
|
permission_classes = [IsAuthenticatedAndActive, IsEditorOrAbove]
|
|
throttle_scope = 'publisher'
|
|
throttle_classes = [DebugScopedRateThrottle]
|
|
|
|
def __init__(self, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.publisher_service = PublisherService()
|
|
|
|
@action(detail=False, methods=['post'], url_path='publish')
|
|
def publish(self, request):
|
|
"""
|
|
Publish content or site to destinations.
|
|
|
|
Request body:
|
|
{
|
|
"content_id": 123, # Optional: content to publish
|
|
"site_blueprint_id": 456, # Optional: site to publish
|
|
"destinations": ["wordpress", "sites"] # Required: list of destinations
|
|
}
|
|
"""
|
|
content_id = request.data.get('content_id')
|
|
site_blueprint_id = request.data.get('site_blueprint_id')
|
|
destinations = request.data.get('destinations', [])
|
|
|
|
if not destinations:
|
|
return error_response(
|
|
'destinations is required',
|
|
status.HTTP_400_BAD_REQUEST,
|
|
request
|
|
)
|
|
|
|
account = request.account
|
|
|
|
if site_blueprint_id:
|
|
# Publish site
|
|
try:
|
|
blueprint = SiteBlueprint.objects.get(id=site_blueprint_id, account=account)
|
|
except SiteBlueprint.DoesNotExist:
|
|
return error_response(
|
|
f'Site blueprint {site_blueprint_id} not found',
|
|
status.HTTP_404_NOT_FOUND,
|
|
request
|
|
)
|
|
|
|
if 'sites' in destinations:
|
|
result = self.publisher_service.publish_to_sites(blueprint)
|
|
return success_response(result, request=request)
|
|
else:
|
|
return error_response(
|
|
'Site publishing only supports "sites" destination',
|
|
status.HTTP_400_BAD_REQUEST,
|
|
request
|
|
)
|
|
|
|
elif content_id:
|
|
# Publish content
|
|
result = self.publisher_service.publish_content(
|
|
content_id,
|
|
destinations,
|
|
account
|
|
)
|
|
return success_response(result, request=request)
|
|
|
|
else:
|
|
return error_response(
|
|
'Either content_id or site_blueprint_id is required',
|
|
status.HTTP_400_BAD_REQUEST,
|
|
request
|
|
)
|
|
|
|
@action(detail=False, methods=['post'], url_path='deploy/(?P<blueprint_id>[^/.]+)')
|
|
def deploy(self, request, blueprint_id):
|
|
"""
|
|
Deploy site blueprint to Sites renderer.
|
|
|
|
POST /api/v1/publisher/deploy/{blueprint_id}/
|
|
"""
|
|
account = request.account
|
|
|
|
try:
|
|
blueprint = SiteBlueprint.objects.get(id=blueprint_id, account=account)
|
|
except SiteBlueprint.DoesNotExist:
|
|
return error_response(
|
|
f'Site blueprint {blueprint_id} not found',
|
|
status.HTTP_404_NOT_FOUND,
|
|
request
|
|
)
|
|
|
|
result = self.publisher_service.publish_to_sites(blueprint)
|
|
|
|
response_status = status.HTTP_202_ACCEPTED if result.get('success') else status.HTTP_400_BAD_REQUEST
|
|
return success_response(result, request=request, status_code=response_status)
|
|
|
|
@action(detail=False, methods=['get'], url_path='status/(?P<id>[^/.]+)')
|
|
def get_status(self, request, id):
|
|
"""
|
|
Get publishing/deployment status.
|
|
|
|
GET /api/v1/publisher/status/{id}/
|
|
"""
|
|
account = request.account
|
|
|
|
# Try deployment record first
|
|
try:
|
|
deployment = DeploymentRecord.objects.get(id=id, account=account)
|
|
return success_response({
|
|
'type': 'deployment',
|
|
'status': deployment.status,
|
|
'version': deployment.version,
|
|
'deployed_version': deployment.deployed_version,
|
|
'deployment_url': deployment.deployment_url,
|
|
'deployed_at': deployment.deployed_at,
|
|
'error_message': deployment.error_message,
|
|
}, request=request)
|
|
except DeploymentRecord.DoesNotExist:
|
|
pass
|
|
|
|
# Try publishing record
|
|
try:
|
|
publishing = PublishingRecord.objects.get(id=id, account=account)
|
|
return success_response({
|
|
'type': 'publishing',
|
|
'status': publishing.status,
|
|
'destination': publishing.destination,
|
|
'destination_url': publishing.destination_url,
|
|
'published_at': publishing.published_at,
|
|
'error_message': publishing.error_message,
|
|
}, request=request)
|
|
except PublishingRecord.DoesNotExist:
|
|
return error_response(
|
|
f'Record {id} not found',
|
|
status.HTTP_404_NOT_FOUND,
|
|
request
|
|
)
|
|
|