Skip to content
Snippets Groups Projects
views.py 3.39 KiB
Newer Older
from django import forms
from django.conf import settings
from django.http import HttpResponse

from rest_framework import viewsets
from rest_framework import views
from rest_framework import response
from rest_framework.decorators import list_route, detail_route
from . import actors
from . import authentication
from . import renderers
from . import serializers
from . import webfinger


class FederationMixin(object):
    def dispatch(self, request, *args, **kwargs):
        if not settings.FEDERATION_ENABLED:
            return HttpResponse(status=405)
        return super().dispatch(request, *args, **kwargs)


class InstanceActorViewSet(FederationMixin, viewsets.GenericViewSet):
    lookup_field = 'actor'
    lookup_value_regex = '[a-z]*'
    authentication_classes = [
        authentication.SignatureAuthentication]
    permission_classes = []
    renderer_classes = [renderers.ActivityPubRenderer]
    def get_object(self):
        try:
            return actors.SYSTEM_ACTORS[self.kwargs['actor']]
        except KeyError:
            raise Http404
    def retrieve(self, request, *args, **kwargs):
        system_actor = self.get_object()
        actor = system_actor.get_actor_instance()
        serializer = serializers.ActorSerializer(actor)
        return response.Response(serializer.data, status=200)

    @detail_route(methods=['get', 'post'])
    def inbox(self, request, *args, **kwargs):
        system_actor = self.get_object()
        handler = getattr(system_actor, '{}_inbox'.format(
            request.method.lower()
        ))
        try:
            data = handler(request.data, actor=request.actor)
        except NotImplementedError:
            return response.Response(status=405)
        return response.Response(data, status=200)

    @detail_route(methods=['get', 'post'])
    def outbox(self, request, *args, **kwargs):
        system_actor = self.get_object()
        handler = getattr(system_actor, '{}_outbox'.format(
            request.method.lower()
        ))
        try:
            data = handler(request.data, actor=request.actor)
        except NotImplementedError:
            return response.Response(status=405)
        return response.Response(data, status=200)


class WellKnownViewSet(FederationMixin, viewsets.GenericViewSet):
    authentication_classes = []
    permission_classes = []
    renderer_classes = [renderers.WebfingerRenderer]

    @list_route(methods=['get'])
    def webfinger(self, request, *args, **kwargs):
        try:
            resource_type, resource = webfinger.clean_resource(
                request.GET['resource'])
            cleaner = getattr(webfinger, 'clean_{}'.format(resource_type))
            result = cleaner(resource)
        except forms.ValidationError as e:
            return response.Response({
                'errors': {
                    'resource': e.message
                }
            }, status=400)
        except KeyError:
            return response.Response({
                'errors': {
                    'resource': 'This field is required',
                }
            }, status=400)

        handler = getattr(self, 'handler_{}'.format(resource_type))
        data = handler(result)

        return response.Response(data)

    def handler_acct(self, clean_result):
        username, hostname = clean_result
        actor = actors.SYSTEM_ACTORS[username].get_actor_instance()
        return serializers.ActorWebfingerSerializer(actor).data