Working towards a queue of follow requests
This commit is contained in:
parent
ae6171f357
commit
5c69288d48
3 changed files with 28 additions and 22 deletions
|
@ -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,8 +151,8 @@ 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):
|
||||||
if domain.startswith("http"):
|
if domain.startswith("http"):
|
||||||
|
@ -170,8 +169,8 @@ 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:
|
||||||
pass
|
pass
|
||||||
|
@ -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())
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
Loading…
Reference in a new issue