aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/db/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/db/base.py')
-rw-r--r--mediagoblin/db/base.py87
1 files changed, 44 insertions, 43 deletions
diff --git a/mediagoblin/db/base.py b/mediagoblin/db/base.py
index a425343b..a62cbebc 100644
--- a/mediagoblin/db/base.py
+++ b/mediagoblin/db/base.py
@@ -13,8 +13,6 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import datetime
-
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import inspect
@@ -30,11 +28,7 @@ class GMGTableBase(object):
HARD_DELETE = "hard-deletion"
SOFT_DELETE = "soft-deletion"
- __default_model_args__ = {
- "deletion": HARD_DELETE,
- "soft_deletion_field": "deleted",
- "soft_deletion_retain": ("id",)
- }
+ deletion_mode = HARD_DELETE
@property
def _session(self):
@@ -47,11 +41,6 @@ class GMGTableBase(object):
if not DISABLE_GLOBALS:
query = Session.query_property()
- def get_model_arg(self, argument):
- model_args = self.__default_model_args__.copy()
- model_args.update(getattr(self, "__model_args__", {}))
- return model_args.get(argument)
-
def get(self, key):
return getattr(self, key)
@@ -70,42 +59,54 @@ class GMGTableBase(object):
else:
sess.flush()
- def delete(self, commit=True):
+ def delete(self, commit=True, deletion=None):
""" Delete the object either using soft or hard deletion """
- if self.get_model_arg("deletion") == self.HARD_DELETE:
- return self.hard_delete(commit)
- elif self.get_model_arg("deletion") == self.SOFT_DELETE:
- return self.soft_delete(commit)
+ # Get the setting in the model args if none has been specified.
+ if deletion is None:
+ deletion = self.deletion_mode
+
+ # Hand off to the correct deletion function.
+ if deletion == self.HARD_DELETE:
+ return self.hard_delete(commit=commit)
+ elif deletion == self.SOFT_DELETE:
+ return self.soft_delete(commit=commit)
else:
raise ValueError(
- "__model_args__['deletion'] is an invalid value %s" % (
- self.get_model_arg("deletion")
- ))
+ "Invalid deletion mode {mode!r}".format(
+ mode=deletion
+ )
+ )
def soft_delete(self, commit):
- # Find the deletion field
- field_name = self.get_model_arg("soft_deletion_field")
-
- # We can't use self.__table__.columns as it only shows it of the
- # current model and no parent if polymorphism is being used. This
- # will cause problems for example for the User model.
- if field_name not in dir(type(self)):
- raise ValueError("Cannot find soft_deletion_field")
-
- # Store a value in the deletion field
- setattr(self, field_name, datetime.datetime.utcnow())
-
- # Iterate through the fields and remove data
- retain_fields = self.get_model_arg("soft_deletion_retain")
- for field_name in self.__table__.columns.keys():
- # should we skip this field?
- if field_name in retain_fields:
- continue
-
- setattr(self, field_name, None)
-
- # Save the changes
- self.save(commit)
+ # 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
+
+ # This is a special case, we don't want to save any actor if the thing
+ # being soft deleted is a User model as this would create circular
+ # ForeignKeys
+ if not isinstance(self, User):
+ tombstone.actor = User.query.filter_by(
+ id=self.actor
+ ).first()
+ tombstone.object_type = self.object_type
+ tombstone.save()
+
+ # There will be a lot of places where the GenericForeignKey will point
+ # to the model, we want to remap those to our tombstone.
+ gmrs = GenericModelReference.query.filter_by(
+ obj_pk=self.id,
+ model_type=self.__tablename__
+ ).update({
+ "obj_pk": tombstone.id,
+ "model_type": tombstone.__tablename__,
+ })
+
+ # Now we can go ahead and actually delete the model.
+ return self.hard_delete(commit=commit)
def hard_delete(self, commit):
"""Delete the object and commit the change immediately by default"""