415 lines
9.6 KiB
Go
415 lines
9.6 KiB
Go
|
package exporting
|
||
|
|
||
|
import (
|
||
|
"archive/zip"
|
||
|
"fmt"
|
||
|
|
||
|
"code.nonshy.com/nonshy/website/pkg/log"
|
||
|
"code.nonshy.com/nonshy/website/pkg/models"
|
||
|
"gorm.io/gorm"
|
||
|
)
|
||
|
|
||
|
// ExportModels is the entry point function to export all data tables about a user.
|
||
|
func ExportModels(zw *zip.Writer, user *models.User) error {
|
||
|
type task struct {
|
||
|
Step string
|
||
|
Fn func(*zip.Writer, *models.User) error
|
||
|
}
|
||
|
|
||
|
// List of tables to export. Keep the ordering in sync with
|
||
|
// the AutoMigrate() calls in ../models.go
|
||
|
var todo = []task{
|
||
|
{"User", ExportUserTable},
|
||
|
{"ProfileField", ExportProfileFieldTable},
|
||
|
{"Photo", ExportPhotoTable},
|
||
|
{"PrivatePhoto", ExportPrivatePhotoTable},
|
||
|
{"CertificationPhoto", ExportCertificationPhotoTable},
|
||
|
{"Message", ExportMessageTable},
|
||
|
{"Friend", ExportFriendTable},
|
||
|
{"Block", ExportBlockTable},
|
||
|
{"Feedback", ExportFeedbackTable},
|
||
|
{"Forum", ExportForumTable},
|
||
|
{"Thread", ExportThreadTable},
|
||
|
{"Comment", ExportCommentTable},
|
||
|
{"Like", ExportLikeTable},
|
||
|
{"Notification", ExportNotificationTable},
|
||
|
{"Subscription", ExportSubscriptionTable},
|
||
|
{"CommentPhoto", ExportCommentPhotoTable},
|
||
|
// Note: Poll table is eager-loaded in Thread export
|
||
|
{"PollVote", ExportPollVoteTable},
|
||
|
// Note: AdminGroup info is eager-loaded in User export
|
||
|
{"UserLocation", ExportUserLocationTable},
|
||
|
{"UserNote", ExportUserNoteTable},
|
||
|
{"TwoFactor", ExportTwoFactorTable},
|
||
|
}
|
||
|
for _, item := range todo {
|
||
|
log.Info("Exporting data model: %s", item.Step)
|
||
|
if err := item.Fn(zw, user); err != nil {
|
||
|
return fmt.Errorf("%s: %s", item.Step, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func ExportUserTable(zw *zip.Writer, user *models.User) error {
|
||
|
return ZipJson(zw, "user.json", user)
|
||
|
}
|
||
|
|
||
|
func ExportProfileFieldTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.ProfileField{}
|
||
|
query = models.DB.Model(&models.ProfileField{}).Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "profile_fields.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportPhotoTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Photo{}
|
||
|
query = models.DB.Model(&models.Photo{}).Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
// Copy all the images into the ZIP.
|
||
|
for _, row := range items {
|
||
|
if row.Filename != "" {
|
||
|
if err := ZipPhoto(zw, "photos", row.Filename); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
if row.CroppedFilename != "" {
|
||
|
if err := ZipPhoto(zw, "profile_photos", row.CroppedFilename); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "photos.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportPrivatePhotoTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.PrivatePhoto{}
|
||
|
query = models.DB.Model(&models.PrivatePhoto{}).Where(
|
||
|
"source_user_id = ? OR target_user_id = ?",
|
||
|
user.ID, user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "private_photos.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportCertificationPhotoTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.CertificationPhoto{}
|
||
|
query = models.DB.Model(&models.CertificationPhoto{}).Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
// Copy all the images into the ZIP.
|
||
|
for _, row := range items {
|
||
|
if row.Filename != "" {
|
||
|
if err := ZipPhoto(zw, "certification_photo", row.Filename); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "certification_photo.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportMessageTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Message{}
|
||
|
query = models.DB.Model(&models.Message{}).Where(
|
||
|
"source_user_id = ? OR target_user_id = ?",
|
||
|
user.ID, user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "messages.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportFriendTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Friend{}
|
||
|
query = models.DB.Model(&models.Friend{}).Where(
|
||
|
"source_user_id = ? OR target_user_id = ?",
|
||
|
user.ID, user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "friends.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportBlockTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Block{}
|
||
|
query = models.DB.Model(&models.Block{}).Where(
|
||
|
"source_user_id = ? OR target_user_id = ?",
|
||
|
user.ID, user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "blocks.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportFeedbackTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Feedback{}
|
||
|
photoIDs, _ = user.AllPhotoIDs()
|
||
|
query *gorm.DB
|
||
|
)
|
||
|
|
||
|
// If they have photos, query on those.
|
||
|
if len(photoIDs) > 0 {
|
||
|
query = models.DB.Model(&models.Feedback{}).Where(
|
||
|
"user_id = ? OR (table_name = 'users' AND table_id = ?) OR (table_name = 'photos' AND table_id IN ?)",
|
||
|
user.ID, user.ID, photoIDs,
|
||
|
).Find(&items)
|
||
|
} else {
|
||
|
// Only reports about their user.
|
||
|
query = models.DB.Model(&models.Feedback{}).Where(
|
||
|
"user_id = ? OR (table_name = 'users' AND table_id = ?)",
|
||
|
user.ID, user.ID,
|
||
|
).Find(&items)
|
||
|
}
|
||
|
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "feedback.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportForumTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Forum{}
|
||
|
query = models.DB.Model(&models.Forum{}).Where(
|
||
|
"owner_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "forums.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportThreadTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Thread{}
|
||
|
query = (&models.Thread{}).Preload().Joins(
|
||
|
"JOIN comments ON (comments.id = threads.comment_id)",
|
||
|
).Where(
|
||
|
"comments.user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "threads.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportCommentTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Comment{}
|
||
|
photoIDs, _ = user.AllPhotoIDs()
|
||
|
query *gorm.DB
|
||
|
)
|
||
|
|
||
|
// If they have photos, query on those.
|
||
|
if len(photoIDs) > 0 {
|
||
|
query = models.DB.Model(&models.Comment{}).Where(
|
||
|
"user_id = ? OR (table_name = 'users' AND table_id = ?) OR (table_name = 'photos' AND table_id IN ?)",
|
||
|
user.ID, user.ID, photoIDs,
|
||
|
).Find(&items)
|
||
|
} else {
|
||
|
query = models.DB.Model(&models.Comment{}).Where(
|
||
|
"user_id = ? OR (table_name = 'users' AND table_id = ?)",
|
||
|
user.ID, user.ID,
|
||
|
).Find(&items)
|
||
|
}
|
||
|
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "comments.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportLikeTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Like{}
|
||
|
photoIDs, _ = user.AllPhotoIDs()
|
||
|
query *gorm.DB
|
||
|
)
|
||
|
|
||
|
// If they have photos, query on those.
|
||
|
if len(photoIDs) > 0 {
|
||
|
query = models.DB.Model(&models.Like{}).Where(
|
||
|
"user_id = ? OR (table_name = 'users' AND table_id = ?) OR (table_name = 'photos' AND table_id IN ?)",
|
||
|
user.ID, user.ID, photoIDs,
|
||
|
).Find(&items)
|
||
|
} else {
|
||
|
// Only reports about their user.
|
||
|
query = models.DB.Model(&models.Like{}).Where(
|
||
|
"user_id = ? OR (table_name = 'users' AND table_id = ?)",
|
||
|
user.ID, user.ID,
|
||
|
).Find(&items)
|
||
|
}
|
||
|
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "likes.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportNotificationTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Notification{}
|
||
|
query = models.DB.Model(&models.Notification{}).Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "notifications.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportSubscriptionTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.Subscription{}
|
||
|
query = models.DB.Model(&models.Subscription{}).Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "subscriptions.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportCommentPhotoTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.CommentPhoto{}
|
||
|
query = models.DB.Model(&models.CommentPhoto{}).Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
// Copy all the images into the ZIP.
|
||
|
for _, row := range items {
|
||
|
if row.Filename != "" {
|
||
|
if err := ZipPhoto(zw, "comment_photos", row.Filename); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "comment_photos.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportPollVoteTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.PollVote{}
|
||
|
query = (&models.PollVote{}).Preload().Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "poll_votes.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportUserNoteTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.UserNote{}
|
||
|
query = models.DB.Model(&models.UserNote{}).Where(
|
||
|
"user_id = ? OR about_user_id = ?",
|
||
|
user.ID, user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "user_notes.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportUserLocationTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.UserLocation{}
|
||
|
query = models.DB.Model(&models.UserLocation{}).Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "user_location.json", items)
|
||
|
}
|
||
|
|
||
|
func ExportTwoFactorTable(zw *zip.Writer, user *models.User) error {
|
||
|
var (
|
||
|
items = []*models.TwoFactor{}
|
||
|
query = models.DB.Model(&models.TwoFactor{}).Where(
|
||
|
"user_id = ?",
|
||
|
user.ID,
|
||
|
).Find(&items)
|
||
|
)
|
||
|
if query.Error != nil {
|
||
|
return query.Error
|
||
|
}
|
||
|
|
||
|
return ZipJson(zw, "two_factor.json", items)
|
||
|
}
|