mirror of
https://github.com/penpot/penpot.git
synced 2026-08-29 08:08:46 +00:00
🐛 Cascade profile deletion in objects-gc task
The objects-gc task was performing a hard delete on profiles without cascading the soft-delete to owned teams, projects, and files. This left orphaned objects that were never cleaned up. Now the task invokes delete-object before the hard delete, ensuring all owned resources are properly marked for deletion and cleaned up in subsequent GC iterations. AI-assisted-by: qwen3.7-plus
This commit is contained in:
parent
c9a2b8f12f
commit
6feccaebb3
@ -13,6 +13,7 @@
|
||||
[app.db :as db]
|
||||
[app.features.fdata :as fdata]
|
||||
[app.storage :as sto]
|
||||
[app.tasks.delete-object :as dobj]
|
||||
[integrant.core :as ig]))
|
||||
|
||||
(def ^:private sql:get-profiles
|
||||
@ -33,6 +34,11 @@
|
||||
;; Mark as deleted the storage object
|
||||
(some->> photo-id (sto/touch-object! storage))
|
||||
|
||||
;; Cascade soft-delete to owned teams, projects, files, etc.
|
||||
(dobj/delete-object cfg {:object :profile
|
||||
:id id
|
||||
:deleted-at timestamp})
|
||||
|
||||
(let [affected (-> (db/delete! conn :profile {:id id})
|
||||
(db/get-update-count))]
|
||||
(+ total affected)))
|
||||
|
||||
@ -424,6 +424,38 @@
|
||||
(let [count-after (:count (th/db-exec-one! ["SELECT count(*) FROM http_session_v2 WHERE profile_id = ?" (:id prof)]))]
|
||||
(t/is (= 0 count-after)))))
|
||||
|
||||
(t/deftest profile-deletion-via-gc-cascades
|
||||
(let [prof (th/create-profile* 1)
|
||||
file (th/create-file* 1 {:profile-id (:id prof)
|
||||
:project-id (:default-project-id prof)
|
||||
:is-shared false})
|
||||
team-id (:default-team-id prof)
|
||||
project-id (:default-project-id prof)
|
||||
file-id (:id file)
|
||||
|
||||
deleted-at (ct/minus (ct/now) (ct/duration {:days 1}))]
|
||||
|
||||
(th/db-update! :profile
|
||||
{:deleted-at deleted-at}
|
||||
{:id (:id prof)})
|
||||
|
||||
(let [team-before (th/db-get :team {:id team-id} {::db/remove-deleted false})]
|
||||
(t/is (nil? (:deleted-at team-before))))
|
||||
|
||||
(let [result (th/run-task! :objects-gc {:min-age 0})]
|
||||
(t/is (pos? (:processed result))))
|
||||
|
||||
(let [profile-after (th/db-get :profile {:id (:id prof)} {::db/remove-deleted false})]
|
||||
(t/is (nil? profile-after)))
|
||||
|
||||
(let [team-after (th/db-get :team {:id team-id} {::db/remove-deleted false})]
|
||||
(t/is (nil? team-after)))
|
||||
|
||||
(let [project-after (th/db-get :project {:id project-id} {::db/remove-deleted false})]
|
||||
(t/is (nil? project-after)))
|
||||
|
||||
(let [file-after (th/db-get :file {:id file-id} {::db/remove-deleted false})]
|
||||
(t/is (nil? file-after)))))
|
||||
|
||||
(t/deftest email-blacklist-1
|
||||
(t/is (false? (email.blacklist/enabled? th/*system*)))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user