2023-02-13 08:11:41 +03:00
// Copyright 2023 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2014-04-10 22:20:58 +04:00
2023-02-13 08:11:41 +03:00
package user
2014-04-10 22:20:58 +04:00
import (
2019-12-15 12:51:28 +03:00
"context"
2014-04-10 22:20:58 +04:00
"fmt"
"time"
2021-11-17 15:34:35 +03:00
_ "image/jpeg" // Needed for jpeg support
2023-11-05 15:48:32 +03:00
actions_model "code.gitea.io/gitea/models/actions"
2022-08-25 05:31:57 +03:00
activities_model "code.gitea.io/gitea/models/activities"
2021-12-10 11:14:24 +03:00
asymkey_model "code.gitea.io/gitea/models/asymkey"
2022-05-11 14:16:35 +03:00
auth_model "code.gitea.io/gitea/models/auth"
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2022-06-12 18:51:54 +03:00
git_model "code.gitea.io/gitea/models/git"
2022-06-13 12:37:59 +03:00
issues_model "code.gitea.io/gitea/models/issues"
2022-03-29 09:29:02 +03:00
"code.gitea.io/gitea/models/organization"
2022-05-11 13:09:36 +03:00
access_model "code.gitea.io/gitea/models/perm/access"
2022-05-08 16:46:34 +03:00
pull_model "code.gitea.io/gitea/models/pull"
2021-12-10 04:27:50 +03:00
repo_model "code.gitea.io/gitea/models/repo"
2021-11-11 10:03:30 +03:00
user_model "code.gitea.io/gitea/models/user"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/setting"
2023-02-13 08:11:41 +03:00
"xorm.io/builder"
2014-04-10 22:20:58 +04:00
)
2023-02-13 08:11:41 +03:00
// deleteUser deletes models associated to an user.
func deleteUser ( ctx context . Context , u * user_model . User , purge bool ) ( err error ) {
2021-11-18 08:58:42 +03:00
e := db . GetEngine ( ctx )
2014-06-27 11:37:01 +04:00
2015-08-17 12:05:37 +03:00
// ***** START: Watch *****
2023-02-13 08:11:41 +03:00
watchedRepoIDs , err := db . FindIDs ( ctx , "watch" , "watch.repo_id" ,
builder . Eq { "watch.user_id" : u . ID } .
And ( builder . Neq { "watch.mode" : repo_model . WatchModeDont } ) )
if err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "get all watches: %w" , err )
2014-04-10 22:20:58 +04:00
}
2023-02-13 08:11:41 +03:00
if err = db . DecrByIDs ( ctx , watchedRepoIDs , "num_watches" , new ( repo_model . Repository ) ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "decrease repository num_watches: %w" , err )
2014-04-12 05:47:39 +04:00
}
2015-08-17 12:05:37 +03:00
// ***** END: Watch *****
2015-03-18 04:51:39 +03:00
2015-08-17 12:05:37 +03:00
// ***** START: Star *****
2023-02-13 08:11:41 +03:00
starredRepoIDs , err := db . FindIDs ( ctx , "star" , "star.repo_id" ,
builder . Eq { "star.uid" : u . ID } )
if err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "get all stars: %w" , err )
2023-02-13 08:11:41 +03:00
} else if err = db . DecrByIDs ( ctx , starredRepoIDs , "num_stars" , new ( repo_model . Repository ) ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "decrease repository num_stars: %w" , err )
2015-08-17 12:05:37 +03:00
}
// ***** END: Star *****
2015-03-18 04:51:39 +03:00
2015-08-17 12:05:37 +03:00
// ***** START: Follow *****
2023-02-13 08:11:41 +03:00
followeeIDs , err := db . FindIDs ( ctx , "follow" , "follow.follow_id" ,
builder . Eq { "follow.user_id" : u . ID } )
if err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "get all followees: %w" , err )
2023-02-13 08:11:41 +03:00
} else if err = db . DecrByIDs ( ctx , followeeIDs , "num_followers" , new ( user_model . User ) ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "decrease user num_followers: %w" , err )
2015-08-17 12:05:37 +03:00
}
2017-05-20 11:48:22 +03:00
2023-02-13 08:11:41 +03:00
followerIDs , err := db . FindIDs ( ctx , "follow" , "follow.user_id" ,
builder . Eq { "follow.follow_id" : u . ID } )
if err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "get all followers: %w" , err )
2023-02-13 08:11:41 +03:00
} else if err = db . DecrByIDs ( ctx , followerIDs , "num_following" , new ( user_model . User ) ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "decrease user num_following: %w" , err )
2014-04-10 22:20:58 +04:00
}
2015-08-17 12:05:37 +03:00
// ***** END: Follow *****
2015-03-18 04:51:39 +03:00
2022-02-17 11:37:48 +03:00
if err = db . DeleteBeans ( ctx ,
2022-08-25 05:31:57 +03:00
& auth_model . AccessToken { UID : u . ID } ,
2022-05-11 13:09:36 +03:00
& repo_model . Collaboration { UserID : u . ID } ,
& access_model . Access { UserID : u . ID } ,
2021-12-12 18:48:20 +03:00
& repo_model . Watch { UserID : u . ID } ,
& repo_model . Star { UID : u . ID } ,
2021-11-17 12:58:31 +03:00
& user_model . Follow { UserID : u . ID } ,
& user_model . Follow { FollowID : u . ID } ,
2022-08-25 05:31:57 +03:00
& activities_model . Action { UserID : u . ID } ,
2022-06-13 12:37:59 +03:00
& issues_model . IssueUser { UID : u . ID } ,
2021-11-11 10:03:30 +03:00
& user_model . EmailAddress { UID : u . ID } ,
2021-11-17 12:58:31 +03:00
& user_model . UserOpenID { UID : u . ID } ,
2022-06-13 12:37:59 +03:00
& issues_model . Reaction { UserID : u . ID } ,
2022-03-29 09:29:02 +03:00
& organization . TeamUser { UID : u . ID } ,
2022-06-13 12:37:59 +03:00
& issues_model . Stopwatch { UserID : u . ID } ,
2021-11-22 12:47:23 +03:00
& user_model . Setting { UserID : u . ID } ,
2022-08-18 02:25:25 +03:00
& user_model . UserBadge { UserID : u . ID } ,
2022-05-08 16:46:34 +03:00
& pull_model . AutoMerge { DoerID : u . ID } ,
& pull_model . ReviewState { UserID : u . ID } ,
2022-11-18 17:23:34 +03:00
& user_model . Redirect { RedirectUserID : u . ID } ,
2023-11-05 15:48:32 +03:00
& actions_model . ActionRunner { OwnerID : u . ID } ,
2015-03-18 04:51:39 +03:00
) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "deleteBeans: %w" , err )
2014-04-10 22:20:58 +04:00
}
2015-03-18 04:51:39 +03:00
2022-05-11 14:16:35 +03:00
if err := auth_model . DeleteOAuth2RelictsByUserID ( ctx , u . ID ) ; err != nil {
return err
}
2022-07-14 10:22:09 +03:00
if purge || ( setting . Service . UserDeleteWithCommentsMaxTime != 0 &&
u . CreatedUnix . AsTime ( ) . Add ( setting . Service . UserDeleteWithCommentsMaxTime ) . After ( time . Now ( ) ) ) {
2021-01-22 05:56:19 +03:00
// Delete Comments
const batchSize = 50
2022-09-05 19:41:16 +03:00
for {
2022-06-13 12:37:59 +03:00
comments := make ( [ ] * issues_model . Comment , 0 , batchSize )
2022-09-05 19:41:16 +03:00
if err = e . Where ( "type=? AND poster_id=?" , issues_model . CommentTypeComment , u . ID ) . Limit ( batchSize , 0 ) . Find ( & comments ) ; err != nil {
2021-01-22 05:56:19 +03:00
return err
}
if len ( comments ) == 0 {
break
}
for _ , comment := range comments {
2022-06-13 12:37:59 +03:00
if err = issues_model . DeleteComment ( ctx , comment ) ; err != nil {
2021-01-22 05:56:19 +03:00
return err
}
}
}
// Delete Reactions
2022-06-13 12:37:59 +03:00
if err = issues_model . DeleteReaction ( ctx , & issues_model . ReactionOptions { DoerID : u . ID } ) ; err != nil {
2021-01-22 05:56:19 +03:00
return err
2021-01-17 23:48:38 +03:00
}
}
2022-03-22 04:09:45 +03:00
// ***** START: Branch Protections *****
{
const batchSize = 50
for start := 0 ; ; start += batchSize {
2022-06-12 18:51:54 +03:00
protections := make ( [ ] * git_model . ProtectedBranch , 0 , batchSize )
2022-03-22 04:09:45 +03:00
// @perf: We can't filter on DB side by u.ID, as those IDs are serialized as JSON strings.
// We could filter down with `WHERE repo_id IN (reposWithPushPermission(u))`,
// though that query will be quite complex and tricky to maintain (compare `getRepoAssignees()`).
// Also, as we didn't update branch protections when removing entries from `access` table,
// it's safer to iterate all protected branches.
if err = e . Limit ( batchSize , start ) . Find ( & protections ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "findProtectedBranches: %w" , err )
2022-03-22 04:09:45 +03:00
}
if len ( protections ) == 0 {
break
}
for _ , p := range protections {
2023-01-16 11:00:22 +03:00
if err := git_model . RemoveUserIDFromProtectedBranch ( ctx , p , u . ID ) ; err != nil {
return err
2022-03-22 04:09:45 +03:00
}
}
}
}
// ***** END: Branch Protections *****
2015-08-17 12:05:37 +03:00
// ***** START: PublicKey *****
2022-05-20 17:08:52 +03:00
if _ , err = db . DeleteByBean ( ctx , & asymkey_model . PublicKey { OwnerID : u . ID } ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "deletePublicKeys: %w" , err )
2014-04-10 22:20:58 +04:00
}
2015-08-17 12:05:37 +03:00
// ***** END: PublicKey *****
2014-04-10 22:20:58 +04:00
2018-12-18 19:26:26 +03:00
// ***** START: GPGPublicKey *****
2021-12-10 11:14:24 +03:00
keys , err := asymkey_model . ListGPGKeys ( ctx , u . ID , db . ListOptions { } )
2021-02-04 12:16:21 +03:00
if err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "ListGPGKeys: %w" , err )
2021-02-04 12:16:21 +03:00
}
// Delete GPGKeyImport(s).
for _ , key := range keys {
2022-05-20 17:08:52 +03:00
if _ , err = db . DeleteByBean ( ctx , & asymkey_model . GPGKeyImport { KeyID : key . KeyID } ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "deleteGPGKeyImports: %w" , err )
2021-02-04 12:16:21 +03:00
}
}
2022-05-20 17:08:52 +03:00
if _ , err = db . DeleteByBean ( ctx , & asymkey_model . GPGKey { OwnerID : u . ID } ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "deleteGPGKeys: %w" , err )
2018-12-18 19:26:26 +03:00
}
// ***** END: GPGPublicKey *****
2015-08-14 21:48:05 +03:00
// Clear assignee.
2022-06-13 12:37:59 +03:00
if _ , err = db . DeleteByBean ( ctx , & issues_model . IssueAssignees { AssigneeID : u . ID } ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "clear assignee: %w" , err )
2015-08-14 21:48:05 +03:00
}
2017-02-22 10:14:37 +03:00
// ***** START: ExternalLoginUser *****
2021-11-28 17:11:58 +03:00
if err = user_model . RemoveAllAccountLinks ( ctx , u ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "ExternalLoginUser: %w" , err )
2017-02-22 10:14:37 +03:00
}
// ***** END: ExternalLoginUser *****
2023-12-25 23:25:29 +03:00
if _ , err = db . DeleteByID [ user_model . User ] ( ctx , u . ID ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "delete: %w" , err )
2015-03-18 04:51:39 +03:00
}
2015-08-17 12:05:37 +03:00
return nil
2014-06-21 08:51:41 +04:00
}