From ff44834b34b94b7c4bda594c7f23462f8db8a149 Mon Sep 17 00:00:00 2001 From: Marnanel Thurman Date: Wed, 3 Oct 2018 19:36:39 +0100 Subject: [PATCH] Intermediate checkin for AsyncResult --- django_kepi/__init__.py | 14 +++++++ django_kepi/models.py | 6 +++ django_kepi/views.py | 75 +++++++++++++++++++++++++++++++++++- test_urls.py | 1 + things_for_testing/models.py | 4 ++ 5 files changed, 98 insertions(+), 2 deletions(-) diff --git a/django_kepi/__init__.py b/django_kepi/__init__.py index 25dc1ae..03954de 100644 --- a/django_kepi/__init__.py +++ b/django_kepi/__init__.py @@ -61,6 +61,20 @@ def resolve(identifier, f_type=None): return None +def create(fields): + + if 'type' not in fields: + raise ValueError('objects must have a type') + + if fields['type'] not in object_type_registry: + raise ValueError('type {} is unknown'.format(fields['type'],)) + + cls = object_type_registry[t] + + result = cls.activitypub_create(fields) + + return result + class TombstoneException(Exception): def __init__(self, *args, **kwargs): diff --git a/django_kepi/models.py b/django_kepi/models.py index dba88f3..98cd75d 100644 --- a/django_kepi/models.py +++ b/django_kepi/models.py @@ -311,6 +311,10 @@ class Activity(models.Model): def find_activity(cls, url): return cls.objects.get(identifier=url) + @classmethod + def activitypub_create(cls, fields): + return cls.create(value, local=False) + @classmethod def create(cls, value, local=False): @@ -417,5 +421,7 @@ class Activity(models.Model): # TODO: there should be a clean() method with the same # checks as create(). +######################################## + Activity.register_all_activity_types() diff --git a/django_kepi/views.py b/django_kepi/views.py index 972f40e..77e7b42 100644 --- a/django_kepi/views.py +++ b/django_kepi/views.py @@ -1,9 +1,10 @@ -from django_kepi import ATSIGN_CONTEXT, NeedToFetchException +from django_kepi import ATSIGN_CONTEXT, NeedToFetchException, create +from django_kepi import create as kepi_create from django.shortcuts import render, get_object_or_404 import django.views from django.http import HttpResponse, JsonResponse from django.contrib.auth.decorators import login_required -from django_kepi.models import QuarantinedMessage +from django_kepi.models import QuarantinedMessage, QuarantinedMessageNeeds import logging import urllib.parse import json @@ -169,3 +170,73 @@ class InboxView(django.views.View): # We need to support GET (as a collection) # but we don't yet. + +######################################## + +class AsyncResultView(django.views.View): + + def post(self, request, *args, **kwargs): + + uuid_passcode = request.GET['uuid'] + success = bool(request.GET['result']) + + if success: + + if 'body' not in request.POST: + logger.warn('Batch notification had success==True but no body') + raise ValueError() + + body = str(request.POST['body'], encoding='UTF-8') + else: + + if 'body' in request.POST: + logger.warn('Batch notification had success==False but supplied a body') + raise ValueError() + + body = None + + try: + message_need = get_object_or_404(QuarantinedMessageNeeds, uuid_passcode) + except Exception as e: + logger.warn('Batch notification for unknown UUID: %s', + uuid_passcode) + raise e + + if success: + logger.info('Batch processing has retrieved %s:', + message_need.needs_to_fetch) + logger.debug(' -- its contents are %s', body) + else: + logger.debug('Batch processing has failed to retrieve %s:', + message_need.needs_to_fetch) + + if body is not None: + try: + fields = json.loads(body) + except json.decoder.JSONDecodeError: + fields = None + success = False + logger.warn('Body was not JSON. Treating as failure.') + + kepi_create(json.loads(body)) + + logger.debug(' -- trying to deploy all matching messages again') + for need in list(QuarantinedMessageNeeds.objects.filter( + needs_to_fetch = message_need.needs_to_fetch)): + + logger.debug(' -- %s', str(need.message)) + if success: + need.message.deploy() + else: + need.message.delete() + + need.delete() + logger.debug(' -- finished deployment attempts') + + return HttpResponse( + status = 200, + reason = 'All is well', + content = '', + content_type = 'text/plain', + ) + diff --git a/test_urls.py b/test_urls.py index fb87d75..e58d32f 100644 --- a/test_urls.py +++ b/test_urls.py @@ -9,5 +9,6 @@ urlpatterns = [ path('users//following', ThingUserFollowingView.as_view()), path('users//inbox', InboxView.as_view()), path('sharedInbox', InboxView.as_view()), + path('asyncResult', AsyncResultView.as_view()), ] diff --git a/things_for_testing/models.py b/things_for_testing/models.py index 1810b80..7426543 100644 --- a/things_for_testing/models.py +++ b/things_for_testing/models.py @@ -47,6 +47,10 @@ class ThingUser(models.Model): return cls.objects.get(name=name) + @classmethod + def activitypub_create(cls, fields): + raise NotImplementedError() + register_type('Person', ThingUser) class ThingArticle(models.Model):