From 4dec1cd695468ac434bd71eeb329578438054301 Mon Sep 17 00:00:00 2001 From: Jessica Tallon Date: Mon, 15 Dec 2014 11:17:57 +0000 Subject: [PATCH] Fix #1069 - Add deleting images and comments via delete activities --- mediagoblin/federation/views.py | 77 ++++++++++++++++++++++++++++++++- mediagoblin/tests/test_api.py | 69 +++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 1 deletion(-) diff --git a/mediagoblin/federation/views.py b/mediagoblin/federation/views.py index ad7baacf..40873cea 100644 --- a/mediagoblin/federation/views.py +++ b/mediagoblin/federation/views.py @@ -231,7 +231,7 @@ def feed_endpoint(request): return json_error("Invalid activity provided.") # Check that the verb is valid - if data["verb"] not in ["post", "update"]: + if data["verb"] not in ["post", "update", "delete"]: return json_error("Verb not yet implemented", 501) # We need to check that the user they're posting to is @@ -430,6 +430,81 @@ def feed_endpoint(request): return json_response(activity.serialize(request)) + elif data["verb"] == "delete": + obj = data.get("object", None) + if obj is None: + return json_error("Could not find 'object' element.") + + if "objectType" not in obj: + return json_error("No objectType specified.") + + if "id" not in obj: + return json_error("Object ID has not been specified.") + + # Parse out the object ID + obj_id = int(extract_url_arguments( + url=obj["id"], + urlmap=request.app.url_map + )["id"]) + + if obj.get("objectType", None) == "comment": + # Find the comment asked for + comment = MediaComment.query.filter_by( + id=obj_id, + author=request.user.id + ).first() + + if comment is None: + return json_error( + "No such 'comment' with id '{0}'.".format(obj_id) + ) + + # Make a delete activity + generator = create_generator(request) + activity = create_activity( + verb="delete", + actor=request.user, + obj=comment, + generator=generator + ) + + # Unfortunately this has to be done while hard deletion exists + context = activity.serialize(request) + + # now we can delete the comment + comment.delete() + + return json_response(context) + + if obj.get("objectType", None) == "image": + # Find the image + entry = MediaEntry.query.filter_by( + id=obj_id, + uploader=request.user.id + ).first() + + if entry is None: + return json_error( + "No such 'image' with id '{0}'.".format(obj_id) + ) + + # Make the delete activity + generator = create_generator(request) + activity = create_activity( + verb="delete", + actor=request.user, + obj=entry, + generator=generator + ) + + # This is because we have hard deletion + context = activity.serialize(request) + + # Now we can delete the image + entry.delete() + + return json_response(context) + elif request.method != "GET": return json_error( "Unsupported HTTP method {0}".format(request.method), diff --git a/mediagoblin/tests/test_api.py b/mediagoblin/tests/test_api.py index 83857d39..a4cb21d6 100644 --- a/mediagoblin/tests/test_api.py +++ b/mediagoblin/tests/test_api.py @@ -492,3 +492,72 @@ class TestAPI(object): assert "url" in data assert "links" in data assert data["objectType"] == "image" + + def test_delete_media_by_activity(self, test_app): + """ Test that an image can be deleted by a delete activity to feed """ + response, data = self._upload_image(test_app, GOOD_JPG) + response, data = self._post_image_to_feed(test_app, data) + object_id = data["object"]["id"] + + activity = { + "verb": "delete", + "object": { + "id": object_id, + "objectType": "image", + } + } + + response = self._activity_to_feed(test_app, activity)[1] + + # Check the media is no longer in the database + media_id = int(object_id.split("/")[-2]) + media = MediaEntry.query.filter_by(id=media_id).first() + + assert media is None + + # Check we've been given the full delete activity back + assert "id" in response + assert response["verb"] == "delete" + assert "object" in response + assert response["object"]["id"] == object_id + assert response["object"]["objectType"] == "image" + + def test_delete_comment_by_activity(self, test_app): + """ Test that a comment is deleted by a delete activity to feed """ + # First upload an image to comment against + response, data = self._upload_image(test_app, GOOD_JPG) + response, data = self._post_image_to_feed(test_app, data) + + # Post a comment to delete + activity = { + "verb": "post", + "object": { + "objectType": "comment", + "content": "This is a comment.", + "inReplyTo": data["object"], + } + } + + comment = self._activity_to_feed(test_app, activity)[1] + + # Now delete the image + activity = { + "verb": "delete", + "object": { + "id": comment["object"]["id"], + "objectType": "comment", + } + } + + delete = self._activity_to_feed(test_app, activity)[1] + + # Verify the comment no longer exists + comment_id = int(comment["object"]["id"].split("/")[-2]) + assert MediaComment.query.filter_by(id=comment_id).first() is None + + # Check we've got a delete activity back + assert "id" in delete + assert delete["verb"] == "delete" + assert "object" in delete + assert delete["object"]["id"] == comment["object"]["id"] + assert delete["object"]["objectType"] == "comment" -- 2.25.1