Repository: CERT-Polska/mwdb-core (language: python)

Issue:
Unable to delete sample
**Environment information**
* MWDB version (from `/about`): 2.8.1
* Installation method:
  - [ ] mwdb.cert.pl service
  - [x] From PyPi (`pip install mwdb-core`)
  - [ ] From docker-compose
  - [ ] Other (please explain)
* Plugins installed:

**Behaviour the bug (what happened?)**

1. Try to remove a sample
2. Get an internal error

**Expected behaviour**

1. Try to remove a sample
2. Sample gets deleted

**Reproduction Steps**

1. Try to remove a sample
2. Get an internal error

**Additional context**

```python
Oct 24 11:48:23 stalkie uwsgi[799]: [ERROR] uWSGIWorker1Core0 - service.error_router:76 - Unhandled exception occurred
Oct 24 11:48:23 stalkie uwsgi[799]: Traceback (most recent call last):
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/flask/app.py", line 1516, in full_dispatch_request
Oct 24 11:48:23 stalkie uwsgi[799]:     rv = self.dispatch_request()
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/flask/app.py", line 1502, in dispatch_request
Oct 24 11:48:23 stalkie uwsgi[799]:     return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/flask_restful/__init__.py", line 467, in wrapper
Oct 24 11:48:23 stalkie uwsgi[799]:     resp = resource(*args, **kwargs)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/flask_limiter/extension.py", line 1036, in __inner
Oct 24 11:48:23 stalkie uwsgi[799]:     return current_app.ensure_sync(obj)(*a, **k)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/flask_limiter/extension.py", line 1036, in __inner
Oct 24 11:48:23 stalkie uwsgi[799]:     return current_app.ensure_sync(obj)(*a, **k)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/flask_limiter/extension.py", line 1036, in __inner
Oct 24 11:48:23 stalkie uwsgi[799]:     return current_app.ensure_sync(obj)(*a, **k)
Oct 24 11:48:23 stalkie uwsgi[799]:   [Previous line repeated 13 more times]
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/flask/views.py", line 84, in view
Oct 24 11:48:23 stalkie uwsgi[799]:     return current_app.ensure_sync(self.dispatch_request)(*args, **kwargs)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/flask_restful/__init__.py", line 582, in dispatch_request
Oct 24 11:48:23 stalkie uwsgi[799]:     resp = meth(*args, **kwargs)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/mwdb/resources/__init__.py", line 47, in endpoint
Oct 24 11:48:23 stalkie uwsgi[799]:     return f(*args, **kwargs)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/mwdb/resources/__init__.py", line 31, in endpoint
Oct 24 11:48:23 stalkie uwsgi[799]:     return f(*args, **kwargs)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/mwdb/resources/object.py", line 360, in delete
Oct 24 11:48:23 stalkie uwsgi[799]:     db.session.commit()
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/scoping.py", line 163, in do
Oct 24 11:48:23 stalkie uwsgi[799]:     return getattr(self.registry(), name)(*args, **kwargs)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1042, in commit
Oct 24 11:48:23 stalkie uwsgi[799]:     self.transaction.commit()
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 504, in commit
Oct 24 11:48:23 stalkie uwsgi[799]:     self._prepare_impl()
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 483, in _prepare_impl
Oct 24 11:48:23 stalkie uwsgi[799]:     self.session.flush()
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 2523, in flush
Oct 24 11:48:23 stalkie uwsgi[799]:     self._flush(objects)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 2664, in _flush
Oct 24 11:48:23 stalkie uwsgi[799]:     transaction.rollback(_capture_exception=True)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
Oct 24 11:48:23 stalkie uwsgi[799]:     compat.raise_(
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 178, in raise_
Oct 24 11:48:23 stalkie uwsgi[799]:     raise exception
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 2624, in _flush
Oct 24 11:48:23 stalkie uwsgi[799]:     flush_context.execute()
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/unitofwork.py", line 422, in execute
Oct 24 11:48:23 stalkie uwsgi[799]:     rec.execute(self)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/unitofwork.py", line 538, in execute
Oct 24 11:48:23 stalkie uwsgi[799]:     self.dependency_processor.process_deletes(uow, states)
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/dependency.py", line 1104, in process_deletes
Oct 24 11:48:23 stalkie uwsgi[799]:     self._run_crud(
Oct 24 11:48:23 stalkie uwsgi[799]:   File "/home/mwdb/venv/lib/python3.9/site-packages/sqlalchemy/orm/dependency.py", line 1201, in _run_crud
Oct 24 11:48:23 stalkie uwsgi[799]:     raise exc.StaleDataError(
Oct 24 11:48:23 stalkie uwsgi[799]: sqlalchemy.orm.exc.StaleDataError: DELETE statement on table 'comment' expected to delete 1 row(s); Only 4 were matched.
```



Discussion / hints:
Confirmed, problem appears when deleted object has more than one comment. Will be fixed in incoming patch release.

As a workaround: you can try to delete all comments manually before deleting an object.

Fix patch:
diff --git a/mwdb/model/object.py b/mwdb/model/object.py
index 1d0e56c3d..e60e3bfb3 100644
--- a/mwdb/model/object.py
+++ b/mwdb/model/object.py
@@ -249,10 +249,7 @@ class Object(db.Model):
         "Attribute", backref="object", lazy=True, cascade="save-update, merge, delete"
     )
     comments = db.relationship(
-        "Comment",
-        backref="object",
-        lazy="dynamic",
-        cascade="save-update, merge, delete",
+        "Comment", backref="object", lazy="dynamic", passive_deletes=True
     )
     tags = db.relationship(
         "Tag",
@@ -266,7 +263,10 @@ class Object(db.Model):
     )
 
     comment_authors = db.relationship(
-        "User", secondary="comment", back_populates="commented_objects"
+        "User",
+        secondary="comment",
+        back_populates="commented_objects",
+        passive_deletes=True,
     )
 
     shares = db.relationship(


Test patch:
diff --git a/tests/backend/test_permissions.py b/tests/backend/test_permissions.py
index 4e6f8e821..5ddfbc4ae 100644
--- a/tests/backend/test_permissions.py
+++ b/tests/backend/test_permissions.py
@@ -226,3 +226,16 @@ def test_removing_objects(admin_session):
 
     assert {"tag": "tag123"} in admin_session.get_tags(SampleB.dhash)
 
+
+def test_removing_object_with_comments(admin_session):
+    testCase = RelationTestCase(admin_session)
+    sample = testCase.new_sample("Sample")
+    sample.create()
+
+    admin_session.add_comment(sample.dhash, "comment1")
+    admin_session.add_comment(sample.dhash, "comment2")
+    admin_session.add_comment(sample.dhash, "comment3")
+    admin_session.remove_object(sample.dhash)
+
+    with ShouldRaise(status_code=404):
+        admin_session.get_sample(sample.dhash)