Fix #1069 - Add deleting images and comments via delete activities
authorJessica Tallon <jessica@megworld.co.uk>
Mon, 15 Dec 2014 11:17:57 +0000 (11:17 +0000)
committerJessica Tallon <jessica@megworld.co.uk>
Mon, 15 Dec 2014 11:18:30 +0000 (11:18 +0000)
mediagoblin/federation/views.py
mediagoblin/tests/test_api.py

index ad7baacf9853278c36b45114ce98839859df8ce2..40873cea31e35b9e2c7e6abb7c0e084076cac48c 100644 (file)
@@ -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),
index 83857d39f7e7010b723d6b75f8f1199b87ddd7d2..a4cb21d6d55824d7dfbd43cf13976426ab1f8ae8 100644 (file)
@@ -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"