Noah
aa8d719fc4
* Add ability to (un)subscribe from comment threads on Forums and Photos. * Creating a forum post, replying to a post or adding a comment to a photo automatically subscribes you to be notified when somebody else adds a comment to the thing later. * At the top of each comment thread is a link to disable or re-enable your subscription. You can join a subscription without even needing to comment. If you click to disable notifications, they stay disabled even if you add another comment later.
213 lines
5.3 KiB
Go
213 lines
5.3 KiB
Go
package deletion
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"code.nonshy.com/nonshy/website/pkg/log"
|
|
"code.nonshy.com/nonshy/website/pkg/models"
|
|
"code.nonshy.com/nonshy/website/pkg/photo"
|
|
)
|
|
|
|
// 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{
|
|
{"Notifications", DeleteNotifications},
|
|
{"Likes", DeleteLikes},
|
|
{"Threads", DeleteForumThreads},
|
|
{"Comments", DeleteComments},
|
|
{"Subscriptions", DeleteSubscriptions},
|
|
{"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
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
}
|