@@ -22,7 +22,9 @@ import (
2222 pull_model "code.gitea.io/gitea/models/pull"
2323 repo_model "code.gitea.io/gitea/models/repo"
2424 user_model "code.gitea.io/gitea/models/user"
25+ "code.gitea.io/gitea/modules/log"
2526 "code.gitea.io/gitea/modules/setting"
27+ "code.gitea.io/gitea/modules/storage"
2628
2729 "xorm.io/builder"
2830)
@@ -105,7 +107,7 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
105107
106108 if purge || (setting .Service .UserDeleteWithCommentsMaxTime != 0 &&
107109 u .CreatedUnix .AsTime ().Add (setting .Service .UserDeleteWithCommentsMaxTime ).After (time .Now ())) {
108- // Delete Comments
110+ // Delete Comments with attachments
109111 const batchSize = 50
110112 for {
111113 comments := make ([]* issues_model.Comment , 0 , batchSize )
@@ -117,9 +119,29 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
117119 }
118120
119121 for _ , comment := range comments {
122+ // Delete attachments of the comments
123+ if err := comment .LoadAttachments (ctx ); err != nil {
124+ return err
125+ }
126+
120127 if _ , err = issues_model .DeleteComment (ctx , comment ); err != nil {
121128 return err
122129 }
130+
131+ // delete comment attachments
132+ if _ , err := repo_model .DeleteAttachments (ctx , comment .Attachments , true ); err != nil {
133+ return fmt .Errorf ("delete attachments: %w" , err )
134+ }
135+
136+ for _ , attachment := range comment .Attachments {
137+ if err := storage .Attachments .Delete (repo_model .AttachmentRelativePath (attachment .UUID )); err != nil {
138+ // Even delete files failed, but the attachments has been removed from database, so we
139+ // should not return error but only record the error on logs.
140+ // users have to delete this attachments manually or we should have a
141+ // synchronize between database attachment table and attachment storage
142+ log .Error ("delete attachment[uuid: %s] failed: %v" , attachment .UUID , err )
143+ }
144+ }
123145 }
124146 }
125147
0 commit comments