Permit Mastodon's weird HTML through

This commit is contained in:
Andrew Godwin 2022-11-13 19:03:43 -07:00
parent ddb3436275
commit b5cacb09e3
5 changed files with 45 additions and 4 deletions

View File

@ -7,6 +7,12 @@ from activities.models import FanOut, Post, PostInteraction, TimelineEvent
class PostAdmin(admin.ModelAdmin):
list_display = ["id", "state", "author", "created"]
raw_id_fields = ["to", "mentions"]
actions = ["force_fetch"]
@admin.action(description="Force Fetch")
def force_fetch(self, request, queryset):
for instance in queryset:
instance.debug_fetch()
@admin.register(TimelineEvent)

View File

@ -274,3 +274,18 @@ class Post(StatorModel):
TimelineEvent.add_post(follow.source, post)
# Force it into fanned_out as it's not ours
post.transition_perform(PostStates.fanned_out)
def debug_fetch(self):
"""
Fetches the Post from its original URL again and updates us with it
"""
response = httpx.get(
self.object_uri,
headers={"Accept": "application/json"},
follow_redirects=True,
)
if 200 <= response.status_code < 300:
return self.by_ap(
canonicalise(response.json(), include_security=True),
update=True,
)

View File

@ -1,11 +1,31 @@
import bleach
from bleach.linkifier import LinkifyFilter
from django.utils.safestring import mark_safe
def allow_a(tag: str, name: str, value: str):
if name in ["href", "title", "class"]:
return True
elif name == "rel":
# Only allow rel attributes with a small subset of values
# (we're defending against, for example, rel=me)
rel_values = value.split()
if all(v in ["nofollow", "noopener", "noreferrer", "tag"] for v in rel_values):
return True
return False
def sanitize_post(post_html: str) -> str:
"""
Only allows a, br, p and span tags, and class attributes.
"""
return mark_safe(
bleach.clean(post_html, tags=["a", "br", "p", "span"], attributes=["class"])
cleaner = bleach.Cleaner(
tags=["a", "br", "p", "span"],
attributes={ # type:ignore
"a": allow_a,
"p": ["class"],
"span": ["class"],
},
filters=[LinkifyFilter],
)
return mark_safe(cleaner.clean(post_html))

View File

@ -1,6 +1,6 @@
{% load static %}
{% load activity_tags %}
<div class="post">
<div class="post" data-takahe-id="{{ post.id }}">
{% if post.author.icon_uri %}
<img src="{{post.author.icon_uri}}" class="icon">

View File

@ -118,7 +118,7 @@ class Inbox(View):
# See if we can fetch it right now
async_to_sync(identity.fetch_actor)()
if not identity.public_key:
print("Cannot get actor")
print("Cannot get actor", document["actor"])
return HttpResponseBadRequest("Cannot retrieve actor")
# If there's a "signature" payload, verify against that
if "signature" in document: