Skip to content

Commit

Permalink
Check that Following instance owns ExternalVideo before any action
Browse files Browse the repository at this point in the history
  • Loading branch information
LoanR committed Aug 21, 2024
1 parent 578ff73 commit c28f49b
Show file tree
Hide file tree
Showing 6 changed files with 546 additions and 23 deletions.
65 changes: 46 additions & 19 deletions pod/activitypub/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import requests
from django.urls import reverse
from django.core.exceptions import PermissionDenied

from pod.activitypub.constants import (AP_DEFAULT_CONTEXT, AP_PT_VIDEO_CONTEXT,
BASE_HEADERS)
Expand Down Expand Up @@ -101,7 +102,6 @@ def index_external_videos_page(following: Following, page_url, indexed_external_
def index_external_video(following: Following, video_url):
"""Read a video payload and create an ExternalVideo object"""
ap_video = ap_object(video_url)
logger.warning(f"TODO: Deal with video indexation {ap_video}")
external_video = update_or_create_external_video(payload=ap_video, source_instance=following)
index_es(media=external_video)
return external_video.ap_id
Expand All @@ -110,49 +110,76 @@ def index_external_video(following: Following, video_url):
def external_video_added_by_actor(ap_video, ap_actor):
# Announce for a Video created by a user account
logger.warning("ActivityPub task call ExternalVideo %s creation from actor %s", ap_video, ap_actor)
following_domain = urlparse(ap_video["id"]).netloc
following = Following.objects.get(object__contains=following_domain)
try:
ExternalVideo.objects.get(ap_id=ap_video["id"])
logger.warning("Received an ActivityPub create event from actor %s on an already existing ExternalVideo %s", ap_actor["id"], ap_video["id"])
plausible_following = get_related_following(ap_actor=ap_actor["id"])
existing_e_video = get_external_video_with_related_following(ap_video_id=ap_video["id"], plausible_following=plausible_following)
logger.warning("Received an ActivityPub create event from actor %s on an already existing ExternalVideo %s", ap_actor["id"], existing_e_video.id)
except Following.DoesNotExist:
logger.warning("Received an ActivityPub create event from unknown actor %s", ap_actor["id"])
except PermissionDenied:
logger.warning("Actor %s cannot execute ActivityPub actions", plausible_following.object)
except ExternalVideo.DoesNotExist:
external_video = create_external_video(payload=ap_video, source_instance=following)
external_video = create_external_video(payload=ap_video, source_instance=plausible_following)
index_es(media=external_video)


def external_video_added_by_channel(ap_video, ap_channel):
# Announce for a Video added to a channel
logger.warning("ActivityPub task call ExternalVideo %s creation from channel %s", ap_video, ap_channel)
following_domain = urlparse(ap_video["id"]).netloc
following = Following.objects.get(object__contains=following_domain)
try:
ExternalVideo.objects.get(ap_id=ap_video["id"])
logger.warning("Received an ActivityPub create event from channel %s on an already existing ExternalVideo %s", ap_channel["id"], ap_video["id"])
plausible_following = get_related_following(ap_actor=ap_channel["id"])
existing_e_video = get_external_video_with_related_following(ap_video_id=ap_video["id"], plausible_following=plausible_following)
logger.warning("Received an ActivityPub create event from channel %s on an already existing ExternalVideo %s", ap_channel["id"], existing_e_video.id)
except Following.DoesNotExist:
logger.warning("Received an ActivityPub create event from unknown channel %s", ap_channel["id"])
except PermissionDenied:
logger.warning("Actor %s cannot execute ActivityPub actions", plausible_following.object)
except ExternalVideo.DoesNotExist:
external_video = create_external_video(payload=ap_video, source_instance=following)
external_video = create_external_video(payload=ap_video, source_instance=plausible_following)
index_es(media=external_video)


def external_video_update(ap_video):
def external_video_update(ap_video, ap_actor):
logger.warning("ActivityPub task call ExternalVideo %s update", ap_video["id"])
following_domain = urlparse(ap_video["id"]).netloc
following = Following.objects.get(object__contains=following_domain)
try:
e_video_to_update = ExternalVideo.objects.get(ap_id=ap_video["id"])
external_video = update_external_video(external_video=e_video_to_update, payload=ap_video, source_instance=following)
plausible_following = get_related_following(ap_actor=ap_actor)
e_video_to_update = get_external_video_with_related_following(ap_video_id=ap_video["id"], plausible_following=plausible_following)
external_video = update_external_video(external_video=e_video_to_update, payload=ap_video, source_instance=plausible_following)
index_es(media=external_video)
except Following.DoesNotExist:
logger.warning("Received an ActivityPub update event from unknown actor %s", ap_actor)
except PermissionDenied:
logger.warning("Actor %s cannot execute ActivityPub actions", plausible_following.object)
except ExternalVideo.DoesNotExist:
logger.warning("Received an ActivityPub update event on a nonexistent ExternalVideo %s", ap_video["id"])


def external_video_deletion(ap_video_id):
def external_video_deletion(ap_video_id, ap_actor):
logger.warning("ActivityPub task call ExternalVideo %s delete", ap_video_id)
try:
external_video_to_delete = ExternalVideo.objects.get(ap_id=ap_video_id)
plausible_following = get_related_following(ap_actor=ap_actor)
external_video_to_delete = get_external_video_with_related_following(ap_video_id=ap_video_id, plausible_following=plausible_following)
delete_es(media=external_video_to_delete)
external_video_to_delete.delete()
except Following.DoesNotExist:
logger.warning("Received an ActivityPub delete event from unknown actor %s", ap_actor)
except PermissionDenied:
logger.warning("Actor %s cannot execute ActivityPub actions", plausible_following.object)
except ExternalVideo.DoesNotExist:
logger.warning("Received an ActivityPub delete event on a nonexistent ExternalVideo %s", ap_video_id)
logger.warning("Received an ActivityPub delete event on a nonexistent ExternalVideo %s from actor %s", ap_video_id, plausible_following.object)


def get_related_following(ap_actor):
actor_domain = "{uri.scheme}://{uri.netloc}".format(uri=urlparse(ap_actor))
actor = Following.objects.get(object__startswith=actor_domain)
return actor


def get_external_video_with_related_following(ap_video_id, plausible_following):
if not plausible_following.status == Following.Status.ACCEPTED:
raise PermissionDenied
external_video = ExternalVideo.objects.get(ap_id=ap_video_id, source_instance=plausible_following)
return external_video


def send_video_announce_object(video: Video, follower: Follower):
Expand Down
4 changes: 2 additions & 2 deletions pod/activitypub/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def task_handle_inbox_update(username, data):

obj = ap_object(data["object"])
if obj["type"] == "Video":
return external_video_update(ap_video=obj)
return external_video_update(ap_video=obj, ap_actor=data["actor"])

logger.debug("Ignoring inbox 'Update' action for '%s' object", obj["type"])

Expand All @@ -111,7 +111,7 @@ def task_handle_inbox_delete(username, data):
from .network import external_video_deletion

if data["type"] == "Delete":
return external_video_deletion(ap_video_id=data["object"])
return external_video_deletion(ap_video_id=data["object"], ap_actor=data["actor"])

logger.debug("Ignoring inbox 'Delete' action for '%s' object", data["type"])

Expand Down
5 changes: 4 additions & 1 deletion pod/activitypub/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ def setUp(self):
rendition=self.vr,
)
self.peertube_test_following = Following.objects.create(
object="http://peertube.test", status=Following.Status.NONE
object="http://peertube.test", status=Following.Status.ACCEPTED
)
self.other_peertube_test_following = Following.objects.create(
object="http://other_peertube.test", status=Following.Status.ACCEPTED
)

def tearDown(self):
Expand Down
26 changes: 26 additions & 0 deletions pod/activitypub/tests/fixtures/video_delete_not_owner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
}
],
"to": [
"https://www.w3.org/ns/activitystreams#Public",
"http://peertube.test/video-channels/root_channel/followers",
"http://peertube.test/accounts/peertube/followers",
"http://peertube.test/accounts/root/followers"
],
"cc": [],
"type": "Delete",
"id": "http://peertube.test/videos/watch/717c9d87-c912-4943-a392-49fadf2f235d/delete",
"actor": "http://other_peertube.test/accounts/root",
"object": "http://peertube.test/videos/watch/717c9d87-c912-4943-a392-49fadf2f235d",
"signature": {
"type": "RsaSignature2017",
"creator": "http://peertube.test/accounts/root",
"created": "2024-05-15T13:03:58.608Z",
"signatureValue": "sFcc/OwZVTjo1+iKZ9GSEcS/5KPfY5z1ul7q4nCi59B54fqM1P+WO6fupqD1SB1xYsLtPKDRpnoi3n0+vlPd6AsYN5dL2gHDZ79S0OygzyLFw18GlOSGdr6IFXNdQ7Gr0gTCDu7TXL42HzEes4OXz1LaV0Q+CagvsB96bkV5ZBM="
}
}
Loading

0 comments on commit c28f49b

Please sign in to comment.