2022-08-14 21:40:57 +00:00
|
|
|
package deletion
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2022-08-26 04:21:46 +00:00
|
|
|
"code.nonshy.com/nonshy/website/pkg/log"
|
|
|
|
"code.nonshy.com/nonshy/website/pkg/models"
|
|
|
|
"code.nonshy.com/nonshy/website/pkg/photo"
|
2022-08-14 21:40:57 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// DeleteUser wipes a user and all associated data from the database.
|
|
|
|
func DeleteUser(user *models.User) error {
|
|
|
|
log.Error("BEGIN DeleteUser(%d, %s)", user.ID, user.Username)
|
|
|
|
|
|
|
|
// Remove all linked tables and assets.
|
|
|
|
type remover struct {
|
|
|
|
Step string
|
|
|
|
Fn func(uint64) error
|
|
|
|
}
|
|
|
|
|
|
|
|
var todo = []remover{
|
2022-08-25 04:17:34 +00:00
|
|
|
{"Notifications", DeleteNotifications},
|
|
|
|
{"Likes", DeleteLikes},
|
|
|
|
{"Threads", DeleteForumThreads},
|
|
|
|
{"Comments", DeleteComments},
|
2022-08-27 18:42:48 +00:00
|
|
|
{"Subscriptions", DeleteSubscriptions},
|
2022-08-14 21:40:57 +00:00
|
|
|
{"Photos", DeleteUserPhotos},
|
|
|
|
{"Certification Photo", DeleteCertification},
|
|
|
|
{"Messages", DeleteUserMessages},
|
|
|
|
{"Friends", DeleteFriends},
|
|
|
|
{"Profile Fields", DeleteProfile},
|
|
|
|
}
|
|
|
|
for _, item := range todo {
|
|
|
|
if err := item.Fn(user.ID); err != nil {
|
|
|
|
return fmt.Errorf("%s: %s", item.Step, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the user itself.
|
|
|
|
return user.Delete()
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteUserPhotos scrubs data for deleting a user.
|
|
|
|
func DeleteUserPhotos(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: BEGIN DeleteUserPhotos(%d)", userID)
|
|
|
|
|
|
|
|
// Deeply scrub all user photos.
|
|
|
|
pager := &models.Pagination{
|
|
|
|
Page: 1,
|
|
|
|
PerPage: 20,
|
|
|
|
Sort: "photos.id",
|
|
|
|
}
|
|
|
|
|
|
|
|
for {
|
|
|
|
photos, err := models.PaginateUserPhotos(
|
|
|
|
userID,
|
|
|
|
models.PhotoVisibilityAll,
|
|
|
|
true,
|
|
|
|
pager,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(photos) == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, item := range photos {
|
|
|
|
log.Warn("DeleteUserPhotos(%d): remove file %s", userID, item.Filename)
|
|
|
|
photo.Delete(item.Filename)
|
|
|
|
if item.CroppedFilename != "" {
|
|
|
|
log.Warn("DeleteUserPhotos(%d): remove file %s", userID, item.CroppedFilename)
|
|
|
|
photo.Delete(item.CroppedFilename)
|
|
|
|
}
|
|
|
|
if err := item.Delete(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Error("DeleteUser: END DeleteUserPhotos(%d)", userID)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteCertification scrubs data for deleting a user.
|
|
|
|
func DeleteCertification(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteCertification(%d)", userID)
|
|
|
|
if cert, err := models.GetCertificationPhoto(userID); err == nil {
|
|
|
|
if cert.Filename != "" {
|
|
|
|
log.Warn("DeleteCertification(%d): remove file %s", userID, cert.Filename)
|
|
|
|
photo.Delete(cert.Filename)
|
|
|
|
}
|
|
|
|
return cert.Delete()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteUserMessages scrubs data for deleting a user.
|
|
|
|
func DeleteUserMessages(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteUserMessages(%d)", userID)
|
|
|
|
result := models.DB.Where(
|
|
|
|
"source_user_id = ? OR target_user_id = ?",
|
|
|
|
userID, userID,
|
|
|
|
).Delete(&models.Message{})
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteFriends scrubs data for deleting a user.
|
|
|
|
func DeleteFriends(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteUserFriends(%d)", userID)
|
|
|
|
result := models.DB.Where(
|
|
|
|
"source_user_id = ? OR target_user_id = ?",
|
|
|
|
userID, userID,
|
|
|
|
).Delete(&models.Friend{})
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
2022-08-25 04:17:34 +00:00
|
|
|
// DeleteNotifications scrubs all notifications about a user.
|
|
|
|
func DeleteNotifications(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteNotifications(%d)", userID)
|
|
|
|
result := models.DB.Where(
|
|
|
|
"user_id = ? OR about_user_id = ?",
|
|
|
|
userID, userID,
|
|
|
|
).Delete(&models.Notification{})
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
2022-08-27 18:42:48 +00:00
|
|
|
// DeleteSubscriptions scrubs all notification subscriptions about a user.
|
|
|
|
func DeleteSubscriptions(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteSubscriptions(%d)", userID)
|
|
|
|
result := models.DB.Where(
|
|
|
|
"user_id = ?",
|
|
|
|
userID,
|
|
|
|
).Delete(&models.Subscription{})
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
2022-08-25 04:17:34 +00:00
|
|
|
// DeleteLikes scrubs all Likes about a user.
|
|
|
|
func DeleteLikes(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteLikes(%d)", userID)
|
|
|
|
result := models.DB.Where(
|
|
|
|
"user_id = ? OR (table_name='users' AND table_id=?)",
|
|
|
|
userID, userID,
|
|
|
|
).Delete(&models.Like{})
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
2022-08-14 21:40:57 +00:00
|
|
|
// DeleteProfile scrubs data for deleting a user.
|
|
|
|
func DeleteProfile(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteProfile(%d)", userID)
|
|
|
|
result := models.DB.Where(
|
|
|
|
"user_id = ?",
|
|
|
|
userID,
|
|
|
|
).Delete(&models.ProfileField{})
|
|
|
|
return result.Error
|
|
|
|
}
|
2022-08-25 04:17:34 +00:00
|
|
|
|
|
|
|
// DeleteForumThreads scrubs all forum threads started by the user.
|
|
|
|
func DeleteForumThreads(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteForumThreads(%d)", userID)
|
|
|
|
|
|
|
|
var threadIDs = []uint64{}
|
|
|
|
result := models.DB.Table(
|
|
|
|
"threads",
|
|
|
|
).Joins(
|
|
|
|
"JOIN comments ON (threads.comment_id = comments.id)",
|
|
|
|
).Select(
|
|
|
|
"distinct(threads.id) as id",
|
|
|
|
).Where(
|
|
|
|
"comments.user_id = ?",
|
|
|
|
userID,
|
|
|
|
).Scan(&threadIDs)
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
return fmt.Errorf("Couldn't list thread IDs created by user: %s", result.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Warn("thread IDs to wipe: %+v", threadIDs)
|
|
|
|
|
|
|
|
// Wipe all these threads and their comments.
|
|
|
|
if len(threadIDs) > 0 {
|
|
|
|
result = models.DB.Where(
|
|
|
|
"table_name = ? AND table_id IN ?",
|
|
|
|
"threads", threadIDs,
|
|
|
|
).Delete(&models.Comment{})
|
|
|
|
if result.Error != nil {
|
|
|
|
return fmt.Errorf("Couldn't wipe threads of comments: %s", result.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// And finish the threads off too.
|
|
|
|
result = models.DB.Where(
|
|
|
|
"id IN ?",
|
|
|
|
threadIDs,
|
|
|
|
).Delete(&models.Thread{})
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteComments deletes all comments by the user.
|
|
|
|
func DeleteComments(userID uint64) error {
|
|
|
|
log.Error("DeleteUser: DeleteComments(%d)", userID)
|
|
|
|
|
|
|
|
result := models.DB.Where(
|
|
|
|
"user_id = ?",
|
|
|
|
userID,
|
|
|
|
).Delete(&models.Comment{})
|
|
|
|
return result.Error
|
|
|
|
}
|