From 35aee84b482267df21790d702a9747e38f762d82 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 25 Oct 2021 04:50:19 -0400 Subject: [PATCH 1/5] switch out sanic for custom server --- requirements.txt | 2 +- uncia/middleware.py | 83 +++++++++++++++++++++------------------------ uncia/server.py | 9 +++-- uncia/views.py | 61 +++++++++++++++++---------------- 4 files changed, 76 insertions(+), 79 deletions(-) diff --git a/requirements.txt b/requirements.txt index 009a200..8f08fbe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -izzylib[hasher,http_server,http_signatures,http_urllib_client,sql,template] @ git+https://git.barkshark.xyz/izaliamae/izzylib@5e3f36af449dcc10cc28de09a8e755a252120f78 +izzylib[hasher,http_server_async,http_signatures,http_urllib_client,sql,template] @ git+https://git.barkshark.xyz/izaliamae/izzylib@dd2f3df431212c2a8877e773affea488659d51b2 pyyaml==5.4.1 apscheduler==3.8.0 diff --git a/uncia/middleware.py b/uncia/middleware.py index 8f39723..cc5c606 100644 --- a/uncia/middleware.py +++ b/uncia/middleware.py @@ -1,7 +1,6 @@ from izzylib import logging -from izzylib.http_server import MiddlewareBase +from izzylib.http_server_async import error from izzylib.http_signatures import parse_signature, verify_request, verify_headers - from izzylib.sql.rows import Row from .database import db @@ -53,58 +52,54 @@ def ban_check(s, request): return True -class AuthCheck(MiddlewareBase): - attach = 'request' +async def AuthCheck(request, response): + validated = False + token = request.headers.getone('token') + with db.session as s: + request.token = s.fetch('token', code=token) + request.user = s.fetch('user', id=request.token.id) if request.token else None + request.signature = parse_signature(request.headers.getone('signature')) + request.instance = None + request.actor = None - async def handler(self, request, response): - validated = False - token = request.headers.get('token') + if request.signature: + request.instance = s.get.instance(request.signature.domain) + request.actor = fetch_actor(request.signature.actor) - with db.session as s: - request.token = s.fetch('token', code=token) - request.user = s.fetch('user', id=request.token.id) if request.token else None - request.signature = parse_signature(request.headers.get('signature')) - request.instance = None - request.actor = None + if request.signature.top_domain in blocked_instances: + raise error.Teapot('This teapot kills fascists') - if request.signature: - request.instance = s.get.instance(request.signature.domain) - request.actor = fetch_actor(request.signature.actor) + if ban_check(s, request): + raise error.Forbidden('no') - if request.signature.top_domain in blocked_instances: - return response.text(f'This teapot kills fascists', status=418) + if request.path in ['/inbox', '/actor'] and request.method.lower() == 'post': + ## The actor was deleted, so return a 202 to not get the same message over and over again + if request.actor == False: + raise error.Accepted({'error': 'Could not fetch deleted actor'}) - if ban_check(s, request): - return response.text('no', status=403) + if not request.actor: + raise error.Unauthorized({'error': 'Could not get actor'}) - if request.path in ['/inbox', '/actor'] and request.method.lower() == 'post': - ## The actor was deleted, so return a 202 to not get the same message over and over again - if request.actor == False: - return response.json({'error': 'Could not fetch deleted actor'}, status=202) + try: + data = request.data.json - if not request.actor: - return response.json({'error': 'Could not get actor'}, status=401) + except: + logging.verbose('Failed to parse post data') + raise error.BadRequest({'error': 'Invalid data'}) - try: - data = request.data.json + if type(request.actor).__name__ == 'Row': + logging.warning('Actor data is a db row:', request.actor) + raise error.InternalServerError({'error': f'An unknown error happened'}) - except: - logging.verbose('Failed to parse post data') - return response.json({'error': f'Invalid data'}, status=400) + if not request.instance and data.get('type', '').lower() != 'follow': + raise error.Unauthorized({'error': f'Follow the relay first'}) - if type(request.actor).__name__ == 'Row': - logging.warning('Actor data is a db row:', request.actor) - return response.error({'error': f'An unknown error happened'}, status=500) + validated = verify_request(request, request.actor) - if not request.instance and data.get('type', '').lower() != 'follow': - return response.json({'error': f'Follow the relay first'}, status=401) + if not validated: + logging.debug(f'Not validated: {request.signature.actor}') + raise error.Unauthorized({'error': f'Failed signature check'}) - validated = verify_request(request, request.actor) - - if not validated: - logging.debug(f'Not validated: {request.signature.actor}') - return response.json({'error': f'Failed signature check'}, status=401) - - if any(map(request.path.startswith, auth_paths)) and not request.user: - return response.redir('/login') + if any(map(request.path.startswith, auth_paths)) and not request.user: + raise error.Found('/login') diff --git a/uncia/server.py b/uncia/server.py index 669e7f5..07fab0c 100644 --- a/uncia/server.py +++ b/uncia/server.py @@ -1,6 +1,6 @@ from apscheduler.schedulers.background import BackgroundScheduler from izzylib import logging -from izzylib.http_server import Application, Request +from izzylib.http_server_async import Application from . import __version__, views from .config import config, path, first_start @@ -25,16 +25,15 @@ with db.session as s: listen = config.listen, port = config.port, host = config.host, - workers = config.workers, git_repo = 'https://git.barkshark.xyz/izaliamae/uncia', proto = 'https', tpl_search = [path.frontend], tpl_context = template_context, - class_views = [getattr(views, view) for view in dir(views) if view.startswith('Uncia')] + views = [getattr(views, view) for view in dir(views) if view.startswith('Uncia')], + middleware = [AuthCheck] ) -app.add_middleware(AuthCheck) -app.static('/style', path.frontend.join('style')) +app.add_static('/style', path.frontend.join('style')) def run_retries(): diff --git a/uncia/views.py b/uncia/views.py index 4f2339e..ab1b711 100644 --- a/uncia/views.py +++ b/uncia/views.py @@ -1,7 +1,7 @@ import asyncio, json from izzylib import DotDict, logging -from izzylib.http_server import View +from izzylib.http_server_async import View from . import __version__ from .config import config @@ -12,24 +12,24 @@ from .processing import ProcessData ### Frontend class UnciaHome(View): - paths = ['/'] + __path__ = '/' async def get(self, request, response): with db.session as s: instances = s.get.instance_list() - return response.template('page/home.haml', {'instances': instances}) + response.set_template('page/home.haml', {'instances': instances}) class UnciaAbout(View): - paths = ['/about'] + __path__ = '/about' async def get(self, request, response): - return response.template('page/about.haml') + response.set_template('page/about.haml') class UnciaRegister(View): - paths = ['/register'] + __path__ = '/register' async def get(self, request, response, error=None, message=None, form={}): data = { @@ -38,15 +38,15 @@ class UnciaRegister(View): 'message': message } - return response.template('page/register.haml', data) + response.set_template('page/register.haml', data) async def post(self, request, response): - return await self.get(request, response, form=request.data.form) + return await self.get(request, response, form=await request.form()) class UnciaLogin(View): - paths = ['/login'] + __path__ = '/login' async def get(self, request, response, error=None, message=None, form={}): data = { @@ -55,25 +55,25 @@ class UnciaLogin(View): 'message': message } - return response.template('page/login.haml', data) + response.set_template('page/login.haml', data) async def post(self, request, response): - return await self.get(request, response, form=request.data.form) + return await self.get(request, response, form=await request.form()) class UnciaLogout(View): - paths = ['/logout'] + __path__ = '/logout' async def get(self, request, response): - return response.redir('/') + response.set_redir('/') class UnciaUser(View): - paths = ['/user'] + __path__ = '/user' async def get(self, request, response): - return response.template('page/user.haml') + response.set_template('page/user.haml') async def post(self, request, response): @@ -81,10 +81,10 @@ class UnciaUser(View): class UnciaAdmin(View): - paths = ['/admin'] + __path__ = '/admin' async def get(self, request, response): - return response.template('page/admin.haml') + response.set_template('page/admin.haml') async def post(self, request, response): @@ -94,7 +94,7 @@ class UnciaAdmin(View): ### ActivityPub and AP-related endpoints class UnciaActor(View): - paths = ['/actor', '/inbox'] + __path__ = ['/actor', '/inbox'] async def get(self, request, response): with db.session as s: @@ -125,13 +125,14 @@ class UnciaActor(View): } } - return response.json(data) + response.set_json(data) async def post(self, request, response): if not request.actor: logging.verbose(f'Failed to fetch actor') - return response.json({'error': 'Failed to fetch actor'}) + response.set_json({'error': 'Failed to fetch actor'}) + return processor = ProcessData(request, response, request.data.json) @@ -146,11 +147,12 @@ class UnciaActor(View): logging.debug(f'Body: {request.text}') #return response.json({'error': f'Message type unhandled: {processor.type}'}, status=401) - return response.text('UvU', status=202) + response.set_json({'message': 'UvU'}) + response.status = 202 class UnciaNodeinfo(View): - paths = ['/nodeinfo/2.0.json', '/nodeinfo/2.0'] + __path__ = ['/nodeinfo/2.0.json', '/nodeinfo/2.0'] async def get(self, request, response): with db.session as s: @@ -190,19 +192,20 @@ class UnciaNodeinfo(View): } } - return response.json(data) + response.set_json(data) class UnciaWebfinger(View): - paths = ['/.well-known/webfinger'] + __path__ = '/.well-known/webfinger' async def get(self, request, response): - resource = request.data.query.get('resource') + resource = request.query.get('resource') if resource != f'acct:relay@{config.host}': - return response.text('', status=404) + response.status = 404 + return - return response.json({ + response.set_json({ 'subject': f'acct:relay@{config.host}', 'aliases': [ f'https://{config.host}/actor' @@ -218,10 +221,10 @@ class UnciaWebfinger(View): class UnciaWellknownNodeinfo(View): - paths = ['/.well-known/nodeinfo'] + __path__ = '/.well-known/nodeinfo' async def get(self, request, response): - return response.json({ + response.set_json({ 'links': [ { 'rel': 'http://nodeinfo.diaspora.software/ns/schema/2.0', From f7453694a59cec25571579e09c79ad52e2ce304b Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 25 Oct 2021 06:30:35 -0400 Subject: [PATCH 2/5] bugfixes --- requirements.txt | 2 +- uncia/middleware.py | 12 +++++++++--- uncia/views.py | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/requirements.txt b/requirements.txt index 8f08fbe..e18550a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -izzylib[hasher,http_server_async,http_signatures,http_urllib_client,sql,template] @ git+https://git.barkshark.xyz/izaliamae/izzylib@dd2f3df431212c2a8877e773affea488659d51b2 +izzylib[hasher,http_server_async,http_signatures,http_urllib_client,sql,template] @ git+https://git.barkshark.xyz/izaliamae/izzylib@b2b67b2ed8fbc9a5d04b4156f282ac8beb2ead81 pyyaml==5.4.1 apscheduler==3.8.0 diff --git a/uncia/middleware.py b/uncia/middleware.py index cc5c606..5949c9c 100644 --- a/uncia/middleware.py +++ b/uncia/middleware.py @@ -52,7 +52,7 @@ def ban_check(s, request): return True -async def AuthCheck(request, response): +async def AuthCheck(request): validated = False token = request.headers.getone('token') @@ -82,7 +82,7 @@ async def AuthCheck(request, response): raise error.Unauthorized({'error': 'Could not get actor'}) try: - data = request.data.json + data = await request.json() except: logging.verbose('Failed to parse post data') @@ -95,7 +95,13 @@ async def AuthCheck(request, response): if not request.instance and data.get('type', '').lower() != 'follow': raise error.Unauthorized({'error': f'Follow the relay first'}) - validated = verify_request(request, request.actor) + #validated = verify_request(request, request.actor) + validated = verify_headers( + request.headers.as_dict(), + request.method, + request.path, + request.actor, + await request.body()) if not validated: logging.debug(f'Not validated: {request.signature.actor}') diff --git a/uncia/views.py b/uncia/views.py index ab1b711..2d3883d 100644 --- a/uncia/views.py +++ b/uncia/views.py @@ -134,7 +134,7 @@ class UnciaActor(View): response.set_json({'error': 'Failed to fetch actor'}) return - processor = ProcessData(request, response, request.data.json) + processor = ProcessData(request, response, await request.json()) if processor.valid_type(): loop = asyncio.get_running_loop() From ead1247e8314792d08761c31d5b1b927d5e84018 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 25 Oct 2021 07:43:03 -0400 Subject: [PATCH 3/5] version bump and return activity for actor --- uncia/__init__.py | 2 +- uncia/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uncia/__init__.py b/uncia/__init__.py index b61de7a..e4ccf53 100644 --- a/uncia/__init__.py +++ b/uncia/__init__.py @@ -1,4 +1,4 @@ __package__ = 'Uncia Relay' -__version__ = '0.1.0' +__version__ = '0.1.1' __author__ = 'Zoey Mae' __homepage__ = 'https://git.barkshark.xyz/izaliamae/uncia' diff --git a/uncia/views.py b/uncia/views.py index 2d3883d..2404203 100644 --- a/uncia/views.py +++ b/uncia/views.py @@ -125,7 +125,7 @@ class UnciaActor(View): } } - response.set_json(data) + response.set_json(data, activity=True) async def post(self, request, response): From af5c968d7e3b3827493902d718c82d355b5138f9 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 25 Oct 2021 11:40:28 -0400 Subject: [PATCH 4/5] fix run_retries and add retry commands to manage --- requirements.txt | 3 +-- uncia/database/put.py | 10 +++++++--- uncia/functions.py | 29 +++++++++++++++++++---------- uncia/manage.py | 38 ++++++++++++++++++++++++++++++++++++++ uncia/processing.py | 2 +- uncia/server.py | 34 ++++++++++++++++++++++------------ 6 files changed, 88 insertions(+), 28 deletions(-) diff --git a/requirements.txt b/requirements.txt index e18550a..b513d90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -izzylib[hasher,http_server_async,http_signatures,http_urllib_client,sql,template] @ git+https://git.barkshark.xyz/izaliamae/izzylib@b2b67b2ed8fbc9a5d04b4156f282ac8beb2ead81 +izzylib[hasher,http_server_async,http_signatures,http_urllib_client,sql,template] @ git+https://git.barkshark.xyz/izaliamae/izzylib@cc8f8b09a1c991b4328bf405c88dcf90626adeb7 pyyaml==5.4.1 -apscheduler==3.8.0 diff --git a/uncia/database/put.py b/uncia/database/put.py index 29e286c..c3a724d 100644 --- a/uncia/database/put.py +++ b/uncia/database/put.py @@ -91,20 +91,24 @@ def cmd_instance(self, inbox, actor, followid=None): def cmd_retry(self, inbox, data, headers={}, timestamp=None): - row = self.get.retry(data.id, inbox) + instance = self.get.instance(inbox) + row = instance.retry(data.id) if not row: - instance = self.get.instance(inbox) + logging.verbose(f'Putting new retry in db for {instance.domain}: {data.id}') row = self.insert('retry', msgid = data.id, - inboxid = instanceid, + inboxid = instance.id, data = data, headers = headers, timestamp = timestamp or datetime.now(), return_row = True ) + else: + logging.verbose(f'Retry for {instance.domain} already in db: {data.id}') + return row diff --git a/uncia/functions.py b/uncia/functions.py index 304a87d..22c4b37 100644 --- a/uncia/functions.py +++ b/uncia/functions.py @@ -1,7 +1,7 @@ import json from functools import wraps -from izzylib import LruCache, logging +from izzylib import DotDict, LruCache, logging from izzylib.http_urllib_client import HttpUrllibClient from izzylib.http_urllib_client.error import MaxRetryError @@ -111,19 +111,28 @@ def push_message(inbox, message, headers={}): keyid = f'https://{config.host}/actor#main-key' ) - except MaxRetryError: - return + except MaxRetryError as e: + response = DotDict(status=0, error=e) except Exception as e: - logging.debug(f'push_message: {e.__class__.__name__}: {e}') - return + #logging.debug(f'push_message: {e.__class__.__name__}: {e}') + response = DotDict(status=0, error=e) if response.status not in [200, 202]: - try: - body = response.dict - except: - body = response.text + s.put.retry(inbox, message, headers) - logging.debug(f'Error from {inbox}: {body}') + if response.status: + try: + body = response.dict + except: + body = response.text + logging.debug(f'Error from {inbox}: {response.status} {body}') + + else: + logging.debug(f'Error from {inbox}: {response.error}') + + return + + logging.debug(f'Pushed message to {inbox}:', message['id']) return response diff --git a/uncia/manage.py b/uncia/manage.py index d06058f..7ac38e9 100644 --- a/uncia/manage.py +++ b/uncia/manage.py @@ -13,6 +13,7 @@ from .config import config, dbconfig, path, write_config from .database import db from .functions import fetch_actor, get_inbox from .messages import Message +from .server import retry_instance exe = f'{sys.executable} -m uncia.manage' @@ -95,6 +96,14 @@ python3 -m uncia.manage accept : * python3 -m uncia.manage deny : * Reject a request. +python3 -m uncia.manage retries [domain]: + List all of the current retires. If a domain is specified, only list + retries from that instance + +python3 -m uncia.manage retry [domain]: + Re-run retries. If a domain is specified, only the retries from that + instance will be ran. + python3 -m uncia.manage convert [pleroma or uncia]: Convert the database and config of another relay. Tries to convert a Pleroma Relay by default. @@ -309,6 +318,35 @@ python3 -m uncia.manage convert [pleroma or uncia]: return data or 'No banned domains or users yet' + def cmd_retries(self, domain=None): + with db.session as s: + if domain: + instances = [s.get.instance(domain)] + + else: + instances = s.search('inbox') + + retries = [] + + for instance in instances: + for retry in instance.retries(): + retries.append(f'{retry.timestamp} {retry.msgid}') + + return '\n'.join(retries) + + + def cmd_retry(self, domain=None): + with db.session as s: + if domain: + instances = [s.get.instance(domain)] + + else: + instances = s.search('inbox') + + for instance in instances: + retry_instance(instance) + + def cmd_convert(self, relay='uncia'): if relay.lower() == 'uncia': return self.convert_uncia() diff --git a/uncia/processing.py b/uncia/processing.py index ae5a699..baca470 100644 --- a/uncia/processing.py +++ b/uncia/processing.py @@ -126,7 +126,7 @@ class ProcessData: traceback.print_exc() if not response or response.status not in [200, 202]: - logging.verbose(f'Failed to send object announce to {instance.domain}: {object.id}') + logging.verbose(f'Failed to send announce object to {instance.domain}: {object.id}') s.put.retry(instance.inbox, msg) if response: diff --git a/uncia/server.py b/uncia/server.py index 07fab0c..deee12d 100644 --- a/uncia/server.py +++ b/uncia/server.py @@ -1,10 +1,12 @@ -from apscheduler.schedulers.background import BackgroundScheduler +import asyncio + from izzylib import logging from izzylib.http_server_async import Application from . import __version__, views from .config import config, path, first_start from .database import db +from .functions import push_message from .middleware import AuthCheck @@ -36,23 +38,37 @@ with db.session as s: app.add_static('/style', path.frontend.join('style')) -def run_retries(): +async def run_retries(): + await asyncio.sleep(60 * 60) + with db.session as s: - for instance in s.get.instance_list(): + for instance in s.search('inbox'): retry_instance(instance) def retry_instance(instance): retries = instance.retries() + fails = 0 if not retries: return - logging.debug(f'Retrying {len(retries)} message(s) for {instance.domain}') + logging.verbose(f'Retrying {len(retries)} message(s) for {instance.domain}') for retry in instance.retries(): try: - push_message(instance.inbox, retry.data, headers=retry.headers) + if push_message(instance.inbox, retry.data, headers=retry.headers): + fails = 0 + + with db.session as s: + s.remove('retry', row=retry) + + else: + fails += 1 + + if fails >= 5: + logging.verbose(f'Failed 5 times in a row when retrying messages for {instance.domain}') + return except Exception as e: logging.debug(f'{e.__class__.__name__}: {e}') @@ -64,10 +80,4 @@ def main(): logging.error(f'Uncia has not been configured yet. Please edit {config.envfile} first.') return - scheduler = BackgroundScheduler() - scheduler.add_job(run_retries, 'interval', hours=1) - scheduler.start() - - app.start() - - scheduler.shutdown() + app.start(run_retries()) From 9cf61e5895e0a875b59f9ad446ad6ad1d44a4194 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 26 Oct 2021 06:05:36 -0400 Subject: [PATCH 5/5] add manage command: install --- uncia/manage.py | 75 +++++++++++++++++++++++++++++++++++++++++---- uncia/middleware.py | 6 ++-- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/uncia/manage.py b/uncia/manage.py index 7ac38e9..a53b933 100644 --- a/uncia/manage.py +++ b/uncia/manage.py @@ -1,9 +1,11 @@ -import json, sys +import json, os, sys +from configparser import ConfigParser from datetime import datetime from envbash import load_envbash from getpass import getuser -from izzylib import DotDict, Path, boolean, logging, prompt +from grp import getgrgid +from izzylib import DotDict, Path, boolean, logging, prompt, sudo from izzylib.sql import Database from os import environ as env from urllib.parse import urlparse @@ -51,6 +53,13 @@ class Command: python3 -m uncia.manage help: Show this message. +python3 -m uncia.manage setup: + A series of questions will be asked to generate the env file. + +python3 -m uncia.manage install [systemd or sysv]: + Generate an init service config and put it in the right location. Uses + "systemd" by default, but "sysv" can be specified instead + python3 -m uncia.manage list: List currently subscribed instances. @@ -61,14 +70,14 @@ python3 -m remove : Remove an instance and any retries associated with it from the database. python3 -m uncia.manage ban [*reason]: - Ban a user or domain. A reason may optionally be specified. + Ban a user or domain. A reason may optionally be specified. Quotes not necessary for reason. python3 -m uncia.manage unban : ** Unban a user or domain python3 -m uncia.manage bans ["users" or "domains"]: - List the currently banned domains and users. A ban type ("users"/"domains") - may be specified to only list that type. + List the currently banned domains and users. A ban type ("users"/"domains") + may be specified to only list that type. python3 -m uncia.manage rules [list]: List the current rules. @@ -109,10 +118,64 @@ python3 -m uncia.manage convert [pleroma or uncia]: Pleroma Relay by default. * = The relay needs to be running for the command to work -** = Caching prevents this from taking effect until restart. +** = Caching prevents this from taking effect until restart ''' + def cmd_setup(self): + pass + + + def cmd_install(self, init='systemd'): + if init == 'systemd': + srvfile = path.config.join('uncia.service') + + initcfg = ConfigParser() + initcfg['Unit'] = { + 'Description': 'Uncia Relay', + 'After': 'network.target' + } + + initcfg['Service'] = { + 'User': getuser(), + 'Group': getgrgid(os.getgid()), + 'WorkingDirectory': Path.cwd, + 'ExecStart': f'{sys.executable} -m uncia', + 'Restart': 'always', + 'StartLimitIntervalSec': 30, + 'StartLimitBurst': 5 + } + + initcfg['Install'] = { + 'WantedBy': 'multi-user.target' + } + + with srvfile.open('w') as fd: + initcfg.write(fd) + + elif init == 'sysv': + return '¯\_(ツ)_/¯' + + else: + return f'Error: Invalid service type: {init}\nValid types: systemd, sysv' + + return f'Service file saved to {path.config.join("uncia.service")}' + + # incomplete code to copy service file + #copy_srv = None + + #while type(copy_srv) != bool: + #if copy_srv != None: + #print('Please specify a boolean (yes/no, y/n, true/false, etc)') + + #copy_srv = prompt('Copy service file to /etc/systemd/system/uncia.service?', + #valtype = lambda x: boolean(x, return_value=True), + #default = True + #) + + + + def cmd_config(self, key=None, value=None): with db.session as s: if key and value: diff --git a/uncia/middleware.py b/uncia/middleware.py index 5949c9c..d13866d 100644 --- a/uncia/middleware.py +++ b/uncia/middleware.py @@ -74,9 +74,9 @@ async def AuthCheck(request): raise error.Forbidden('no') if request.path in ['/inbox', '/actor'] and request.method.lower() == 'post': - ## The actor was deleted, so return a 202 to not get the same message over and over again - if request.actor == False: - raise error.Accepted({'error': 'Could not fetch deleted actor'}) + ## The actor was deleted, so return a 200 to not get the same message over and over again + if request.signature and request.actor == False: + raise error.Ok({'error': 'Could not fetch deleted actor'}) if not request.actor: raise error.Unauthorized({'error': 'Could not get actor'})