Fix #5390 - Create migration to delete Notifications and fix Report
authorJessica Tallon <tsyesika@tsyesika.se>
Tue, 19 Jan 2016 09:17:12 +0000 (09:17 +0000)
committerJessica Tallon <tsyesika@tsyesika.se>
Wed, 20 Jan 2016 07:17:19 +0000 (07:17 +0000)
When a user deleted media or other objects any notificationn objects or reports
would cause errors as the object doesn't exist anymore. This now removes them or
sets them to None as expected by the code. This also adds some code to the base
deletion code to make sure this happens when an object is deleted.

mediagoblin/db/base.py
mediagoblin/db/migrations/versions/101510e3a713_removes_graveyard_items_from_.py
mediagoblin/db/migrations/versions/8429e33fdf7_remove_the_graveyard_objects_from_.py [new file with mode: 0644]

index af2337df040dfbdc55dde3dcf90688d95482593c..0f17a3a8d36fbe96f25be1240a93de249bce58d1 100644 (file)
@@ -95,7 +95,8 @@ class GMGTableBase(object):
         # If the item is in any collection then it should be removed, this will
         # cause issues if it isn't. See #5382.
         # Import here to prevent cyclic imports.
-        from mediagoblin.db.models import CollectionItem, GenericModelReference
+        from mediagoblin.db.models import CollectionItem, GenericModelReference, \
+                                          Report, Notification
         
         # Some of the models don't have an "id" field which means they can't be
         # used with GMR, these models won't be in collections because they
@@ -110,13 +111,26 @@ class GMGTableBase(object):
             # If there is no gmr then we've got lucky, a GMR is a requirement of
             # being in a collection.
             if gmr is not None:
+                # Delete collections found
                 items = CollectionItem.query.filter_by(
                     object_id=gmr.id
                 )
-
-                # Delete any CollectionItems found.
                 items.delete()
 
+                # Delete notifications found
+                notifications = Notification.query.filter_by(
+                    object_id=gmr.id
+                )
+                notifications.delete()
+                
+                # Set None on reports found
+                reports = Report.query.filter_by(
+                    object_id=gmr.id
+                )
+                for report in reports:
+                    report.object_id = None
+                    report.save(commit=commit)
+
         # Hand off to the correct deletion function.
         if deletion == self.HARD_DELETE:
             return self.hard_delete(commit=commit)
@@ -133,6 +147,7 @@ class GMGTableBase(object):
         # Create the graveyard version of this model
         # Importing this here due to cyclic imports
         from mediagoblin.db.models import User, Graveyard, GenericModelReference
+        
         tombstone = Graveyard()
         if getattr(self, "public_id", None) is not None:
             tombstone.public_id = self.public_id
index 7eb5aa2c5c5be8c691a52a7bad71e4560fd453f4..800e044862ff8b039352b626f6e7c279db34687c 100644 (file)
@@ -10,8 +10,9 @@ Create Date: 2016-01-12 10:46:26.486610
 revision = '101510e3a713'
 down_revision = '52bf0ccbedc1'
 
-from sqlalchemy import MetaData
 from alembic import op
+from sqlalchemy import MetaData
+from sqlalchemy.sql import and_
 from mediagoblin.db.migration_tools import inspect_table
 
 def upgrade():
diff --git a/mediagoblin/db/migrations/versions/8429e33fdf7_remove_the_graveyard_objects_from_.py b/mediagoblin/db/migrations/versions/8429e33fdf7_remove_the_graveyard_objects_from_.py
new file mode 100644 (file)
index 0000000..8f222a6
--- /dev/null
@@ -0,0 +1,61 @@
+"""Remove the Graveyard objects from CommentNotification objects
+
+Revision ID: 8429e33fdf7
+Revises: 101510e3a713
+Create Date: 2016-01-19 08:01:21.577274
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '8429e33fdf7'
+down_revision = '101510e3a713'
+
+from alembic import op
+from sqlalchemy import MetaData
+from sqlalchemy.sql import and_
+from mediagoblin.db.migration_tools import inspect_table
+
+def upgrade():
+    """
+    This migration is very similiar to that of 101510e3a713. It removes objects
+    from Notification objects which are from Graveyard. It also iterates through
+    any reports which might have been filed and sets the objects to None. 
+    """
+    db = op.get_bind()
+    metadata = MetaData(bind=db)
+    notification_table = inspect_table(metadata, "core__notifications")
+    report_table = inspect_table(metadata, "core__reports")
+    graveyard_table = inspect_table(metadata, "core__graveyard")
+    gmr_table = inspect_table(metadata, "core__generic_model_reference")
+    
+    for tombstone in db.execute(gmr_table.select()):
+        # Look up the gmr for the tombstone8
+        gmr = db.execute(gmr_table.select().where(and_(
+            gmr_table.c.obj_pk == tombstone.id,
+            gmr_table.c.model_type == "core__graveyard"
+        ))).first()
+
+        # If we can't find one we can skip it as it needs one to be part of
+        # the notification objects
+        if gmr is None:
+            continue
+
+        # Delete all notifications which link to the GMR as that's invalid.
+        db.execute(notification_table.delete().where(
+            notification_table.c.object_id == gmr.id
+        ))
+
+        # Deal with reports, we don't want to delete these though, they want to
+        # still exist if the object that was reported was deleted as that can
+        # be part of the resolution, just set it to None.
+        db.execute(report_table.update().where(
+            report_table.c.object_id == gmr.id
+        ).values(object_id=None))
+
+
+def downgrade():
+    """
+    There is nothing to do as this was a data migration, it'll downgrade
+    just fine without any steps. It's not like we can undo the deletions.
+    """
+    pass