Working towards a queue of follow requests

This commit is contained in:
Reid 'arrdem' McKenzie 2022-11-26 17:24:53 -07:00
parent ae6171f357
commit 5c69288d48
3 changed files with 28 additions and 22 deletions

View file

@ -39,7 +39,6 @@ class RelayDatabase(dict):
@property @property
def inboxes(self): def inboxes(self):
return tuple(data["inbox"] for data in self["relay-list"].values()) return tuple(data["inbox"] for data in self["relay-list"].values())
return self["relay-list"]
def generate_key(self): def generate_key(self):
self.PRIVKEY = RSA.generate(4096) self.PRIVKEY = RSA.generate(4096)
@ -152,7 +151,7 @@ class RelayDatabase(dict):
return False return False
def set_followid(self, domain, followid): def set_followid(self, domain, followid):
data = self.get_inbox(domain, fail=True) if (data := self.get_inbox(domain, fail=True)):
data["followid"] = followid data["followid"] = followid
def get_request(self, domain, fail=True): def get_request(self, domain, fail=True):
@ -170,7 +169,7 @@ class RelayDatabase(dict):
domain = urlparse(inbox).hostname domain = urlparse(inbox).hostname
try: try:
request = self.get_request(domain) if (request := self.get_request(domain)):
request["followid"] = followid request["followid"] = followid
except KeyError: except KeyError:
@ -184,6 +183,9 @@ class RelayDatabase(dict):
def del_request(self, domain): def del_request(self, domain):
if domain.startswith("http"): if domain.startswith("http"):
domain = urlparse(inbox).hostname domain = urlparse(domain).hostname
del self["follow-requests"][domain] del self["follow-requests"][domain]
def get_requests(self):
return list(self["follow-requests"].items())

View file

@ -2,6 +2,8 @@ import asyncio
import logging import logging
from relay import misc from relay import misc
from relay.config import RelayConfig
from relay.database import RelayDatabase
async def handle_relay(request, actor, data, software): async def handle_relay(request, actor, data, software):
@ -42,10 +44,19 @@ async def handle_forward(request, actor, data, software):
async def handle_follow(request, actor, data, software): async def handle_follow(request, actor, data, software):
if not request.app.database.add_inbox(actor.shared_inbox, data.id): config: RelayConfig = request.app.config
request.app.database.set_followid(actor.id, data.id) database: RelayDatabase = request.app.database
request.app.database.save() # If the following host is not whitelisted, we want to enqueue the request for review.
# This means saving off the two parameters we need later to issue an appropriate acceptance.
if config.whitelist_enabled and not config.is_whitelisted(data.domain):
database.add_request(actor.id, actor.shared_inbox, data.id)
database.save()
return
if not database.add_inbox(actor.shared_inbox, data.id):
database.set_followid(actor.id, data.id)
database.save()
await misc.request( await misc.request(
actor.shared_inbox, actor.shared_inbox,
@ -67,7 +78,7 @@ async def handle_follow(request, actor, data, software):
async def handle_undo(request, actor, data, software): async def handle_undo(request, actor, data, software):
## If the object is not a Follow, forward it # If the object is not a Follow, forward it
if data["object"]["type"] != "Follow": if data["object"]["type"] != "Follow":
return await handle_forward(request, actor, data, software) return await handle_forward(request, actor, data, software)

View file

@ -65,7 +65,6 @@ async def actor(request):
@register_route("POST", "/actor") @register_route("POST", "/actor")
async def inbox(request): async def inbox(request):
config = request.app.config config = request.app.config
database = request.app.database
# reject if missing signature header # reject if missing signature header
if "signature" not in request.headers: if "signature" not in request.headers:
@ -114,8 +113,9 @@ async def inbox(request):
logging.debug(f"Failed to fetch actor: {data.actorid}") logging.debug(f"Failed to fetch actor: {data.actorid}")
return Response.new_error(400, "failed to fetch actor", "json") return Response.new_error(400, "failed to fetch actor", "json")
# reject if the actor isn't whitelisted while the whiltelist is enabled # Reject if the actor isn't whitelisted while the whiltelist is enabled
elif config.whitelist_enabled and not config.is_whitelisted(data.domain): # An exception is made for follow requests, which we want to enqueue not reject out of hand
elif config.whitelist_enabled and not config.is_whitelisted(data.domain) and data["type"] != "Follow":
logging.debug( logging.debug(
f"Rejected actor for not being in the whitelist: {data.actorid}" f"Rejected actor for not being in the whitelist: {data.actorid}"
) )
@ -140,17 +140,10 @@ async def inbox(request):
logging.debug(f"signature validation failed for: {data.actorid}") logging.debug(f"signature validation failed for: {data.actorid}")
return Response.new_error(401, "signature check failed", "json") return Response.new_error(401, "signature check failed", "json")
# reject if activity type isn't 'Follow' and the actor isn't following
if data["type"] != "Follow" and not database.get_inbox(data.domain):
logging.debug(
f"Rejected actor for trying to post while not following: {data.actorid}"
)
return Response.new_error(401, "access denied", "json")
logging.debug(f">> payload {data}") logging.debug(f">> payload {data}")
await run_processor(request, actor, data, software) resp = await run_processor(request, actor, data, software)
return Response.new(status=202) return resp or Response.new(status=202)
@register_route("GET", "/.well-known/webfinger") @register_route("GET", "/.well-known/webfinger")