mirror of
https://code.eliotberriot.com/funkwhale/funkwhale.git
synced 2025-10-04 04:19:15 +02:00
MRF / Dropping of incoming/outgoing messages based on allow-list
This commit is contained in:
parent
371dc01205
commit
08262529ec
24 changed files with 897 additions and 89 deletions
|
@ -1,5 +1,6 @@
|
|||
import uuid
|
||||
import logging
|
||||
import urllib.parse
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.conf import settings
|
||||
|
@ -122,32 +123,38 @@ def receive(activity, on_behalf_of):
|
|||
from . import serializers
|
||||
from . import tasks
|
||||
from .routes import inbox
|
||||
from funkwhale_api.moderation import mrf
|
||||
|
||||
logger.debug(
|
||||
"[federation] Received activity from %s : %s", on_behalf_of.fid, activity
|
||||
)
|
||||
# we ensure the activity has the bare minimum structure before storing
|
||||
# it in our database
|
||||
serializer = serializers.BaseActivitySerializer(
|
||||
data=activity, context={"actor": on_behalf_of, "local_recipients": True}
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
if not inbox.get_matching_handlers(activity):
|
||||
# discard unhandlable activity
|
||||
return
|
||||
|
||||
if should_reject(
|
||||
fid=serializer.validated_data.get("id"),
|
||||
actor_id=serializer.validated_data["actor"].fid,
|
||||
payload=activity,
|
||||
):
|
||||
payload, updated = mrf.inbox.apply(activity, sender_id=on_behalf_of.fid)
|
||||
if not payload:
|
||||
logger.info(
|
||||
"[federation] Discarding activity due to instance policies %s",
|
||||
"[federation] Discarding activity due to mrf %s",
|
||||
serializer.validated_data.get("id"),
|
||||
)
|
||||
return
|
||||
|
||||
if not inbox.get_matching_handlers(payload):
|
||||
# discard unhandlable activity
|
||||
logger.debug(
|
||||
"[federation] No matching route found for activity, discarding: %s", payload
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
copy = serializer.save()
|
||||
copy = serializer.save(payload=payload, type=payload["type"])
|
||||
except IntegrityError:
|
||||
logger.warning(
|
||||
"[federation] Discarding already elivered activity %s",
|
||||
"[federation] Discarding already delivered activity %s",
|
||||
serializer.validated_data.get("id"),
|
||||
)
|
||||
return
|
||||
|
@ -283,9 +290,19 @@ class OutboxRouter(Router):
|
|||
and may yield data that should be persisted in the Activity model
|
||||
for further delivery.
|
||||
"""
|
||||
from funkwhale_api.common import preferences
|
||||
from . import models
|
||||
from . import tasks
|
||||
|
||||
allow_list_enabled = preferences.get("moderation__allow_list_enabled")
|
||||
allowed_domains = None
|
||||
if allow_list_enabled:
|
||||
allowed_domains = set(
|
||||
models.Domain.objects.filter(allowed=True).values_list(
|
||||
"name", flat=True
|
||||
)
|
||||
)
|
||||
|
||||
for route, handler in self.routes:
|
||||
if not match_route(route, routing):
|
||||
continue
|
||||
|
@ -314,10 +331,10 @@ class OutboxRouter(Router):
|
|||
a = models.Activity(**activity_data)
|
||||
a.uuid = uuid.uuid4()
|
||||
to_inbox_items, to_deliveries, new_to = prepare_deliveries_and_inbox_items(
|
||||
to, "to"
|
||||
to, "to", allowed_domains=allowed_domains
|
||||
)
|
||||
cc_inbox_items, cc_deliveries, new_cc = prepare_deliveries_and_inbox_items(
|
||||
cc, "cc"
|
||||
cc, "cc", allowed_domains=allowed_domains
|
||||
)
|
||||
if not any(
|
||||
[to_inbox_items, to_deliveries, cc_inbox_items, cc_deliveries]
|
||||
|
@ -374,7 +391,14 @@ def match_route(route, payload):
|
|||
return True
|
||||
|
||||
|
||||
def prepare_deliveries_and_inbox_items(recipient_list, type):
|
||||
def is_allowed_url(url, allowed_domains):
|
||||
return (
|
||||
allowed_domains is None
|
||||
or urllib.parse.urlparse(url).hostname in allowed_domains
|
||||
)
|
||||
|
||||
|
||||
def prepare_deliveries_and_inbox_items(recipient_list, type, allowed_domains=None):
|
||||
"""
|
||||
Given a list of recipients (
|
||||
either actor instances, public adresses, a dictionnary with a "type" and "target"
|
||||
|
@ -384,10 +408,12 @@ def prepare_deliveries_and_inbox_items(recipient_list, type):
|
|||
"""
|
||||
from . import models
|
||||
|
||||
if allowed_domains is not None:
|
||||
allowed_domains = set(allowed_domains)
|
||||
allowed_domains.add(settings.FEDERATION_HOSTNAME)
|
||||
local_recipients = set()
|
||||
remote_inbox_urls = set()
|
||||
urls = []
|
||||
|
||||
for r in recipient_list:
|
||||
if isinstance(r, models.Actor):
|
||||
if r.is_local:
|
||||
|
@ -432,7 +458,13 @@ def prepare_deliveries_and_inbox_items(recipient_list, type):
|
|||
values = actors.values("shared_inbox_url", "inbox_url")
|
||||
for v in values:
|
||||
remote_inbox_urls.add(v["shared_inbox_url"] or v["inbox_url"])
|
||||
deliveries = [models.Delivery(inbox_url=url) for url in remote_inbox_urls]
|
||||
|
||||
deliveries = [
|
||||
models.Delivery(inbox_url=url)
|
||||
for url in remote_inbox_urls
|
||||
if is_allowed_url(url, allowed_domains)
|
||||
]
|
||||
urls = [url for url in urls if is_allowed_url(url, allowed_domains)]
|
||||
inbox_items = [
|
||||
models.InboxItem(actor=actor, type=type) for actor in local_recipients
|
||||
]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue