143 lines
6.4 KiB
Go
143 lines
6.4 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/tamakyi/TamaBox/internal/conf"
|
|
)
|
|
|
|
func createOutboxTestUser(t *testing.T, ctx context.Context, store UsersStore, email, domain string) *User {
|
|
t.Helper()
|
|
require.NoError(t, store.Create(ctx, CreateUserOptions{
|
|
Name: domain,
|
|
Password: "test-only-password",
|
|
Email: email,
|
|
Domain: domain,
|
|
}))
|
|
user, err := store.GetByEmail(ctx, email)
|
|
require.NoError(t, err)
|
|
return user
|
|
}
|
|
|
|
func TestPurgeUserContentEnqueuesOwnedR2Objects(t *testing.T) {
|
|
setR2TestConfig(t)
|
|
conn, _ := newTestDB(t)
|
|
ctx := context.Background()
|
|
users := NewUsersStore(conn)
|
|
owner := createOutboxTestUser(t, ctx, users, "[email protected]", "outbox-owner")
|
|
other := createOutboxTestUser(t, ctx, users, "[email protected]", "outbox-other")
|
|
require.NoError(t, conn.Model(owner).Updates(map[string]interface{}{
|
|
"avatar": "https://cdn.example.test/assets/profile-owned.webp", "background": "https://cdn.example.test/assets/default-background.webp", "background_image": "https://cdn.example.test/assets/profile-shared.webp",
|
|
}).Error)
|
|
require.NoError(t, conn.Model(other).Update("background_image", "https://cdn.example.test/assets/profile-shared.webp").Error)
|
|
questions := NewQuestionsStore(conn)
|
|
question, err := questions.Create(ctx, CreateQuestionOptions{UserID: owner.ID, Content: "owned"})
|
|
require.NoError(t, err)
|
|
otherQuestion, err := questions.Create(ctx, CreateQuestionOptions{UserID: other.ID, Content: "other"})
|
|
require.NoError(t, err)
|
|
|
|
images := NewUploadImagesStore(conn)
|
|
owned, err := images.Create(ctx, CreateUploadImageOptions{QuestionID: question.ID, UploaderUserID: owner.ID, Key: "owned.webp"})
|
|
require.NoError(t, err)
|
|
_, err = images.Create(ctx, CreateUploadImageOptions{QuestionID: question.ID, UploaderUserID: owner.ID, Key: "owned.webp"})
|
|
require.NoError(t, err)
|
|
legacy, err := images.Create(ctx, CreateUploadImageOptions{
|
|
QuestionID: question.ID, UploaderUserID: owner.ID, Key: "https://cdn.example.test/assets/legacy.webp",
|
|
})
|
|
require.NoError(t, err)
|
|
external, err := images.Create(ctx, CreateUploadImageOptions{
|
|
QuestionID: question.ID, UploaderUserID: owner.ID, Key: "https://external.example.net/external.webp",
|
|
})
|
|
require.NoError(t, err)
|
|
shared, err := images.Create(ctx, CreateUploadImageOptions{QuestionID: question.ID, UploaderUserID: owner.ID, Key: "shared.webp"})
|
|
require.NoError(t, err)
|
|
require.NoError(t, conn.WithContext(ctx).Create(&UploadImageQuestion{
|
|
UploadImageID: shared.ID, QuestionID: otherQuestion.ID,
|
|
}).Error)
|
|
|
|
conversation, message, err := NewConversationStore(conn).CreateWithFirstMessage(ctx, CreateConversationOptions{
|
|
OwnerID: owner.ID, AskerID: other.ID, MaxMessages: 20,
|
|
}, other.ID, "private")
|
|
require.NoError(t, err)
|
|
require.NotNil(t, conversation)
|
|
messageImages := NewMessageImageStore(conn)
|
|
for _, opts := range []CreateMessageImageOptions{
|
|
{MessageID: message.ID, ObjectKey: "message-key.webp", URL: "https://cdn.example.test/assets/message-key.webp"},
|
|
{MessageID: message.ID, ObjectKey: "owned.webp", URL: "https://cdn.example.test/assets/owned.webp"},
|
|
{MessageID: message.ID, URL: "https://cdn.example.test/assets/message-legacy.webp"},
|
|
{MessageID: message.ID, URL: "https://external.example.net/message-external.webp"},
|
|
} {
|
|
_, err = messageImages.Create(ctx, opts)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
require.NoError(t, users.Deactivate(ctx, owner.ID))
|
|
require.Zero(t, uploadImageCount(t, conn, owned.ID))
|
|
require.Zero(t, uploadImageCount(t, conn, legacy.ID))
|
|
require.Zero(t, uploadImageCount(t, conn, external.ID))
|
|
require.Equal(t, int64(1), uploadImageCount(t, conn, shared.ID))
|
|
var sharedLinks int64
|
|
require.NoError(t, conn.WithContext(ctx).Model(&UploadImageQuestion{}).
|
|
Where("upload_image_id = ? AND question_id = ?", shared.ID, otherQuestion.ID).Count(&sharedLinks).Error)
|
|
require.Equal(t, int64(1), sharedLinks)
|
|
|
|
due, err := NewR2DeleteTaskStore(conn).ListDue(ctx, 20)
|
|
require.NoError(t, err)
|
|
keys := make([]string, 0, len(due))
|
|
for _, task := range due {
|
|
keys = append(keys, task.Key)
|
|
}
|
|
require.ElementsMatch(t, []string{
|
|
"owned.webp", "legacy.webp", "message-key.webp", "message-legacy.webp", "profile-owned.webp", "profile-shared.webp",
|
|
}, keys)
|
|
require.NotContains(t, keys, "shared.webp")
|
|
require.NotContains(t, keys, "external.webp")
|
|
require.NotContains(t, keys, "message-external.webp")
|
|
require.NotContains(t, keys, "default-background.webp")
|
|
var deactivated User
|
|
require.NoError(t, conn.Unscoped().First(&deactivated, owner.ID).Error)
|
|
require.Empty(t, deactivated.Avatar)
|
|
require.Empty(t, deactivated.Background)
|
|
require.Empty(t, deactivated.BackgroundImage)
|
|
other, err = users.GetByID(ctx, other.ID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "https://cdn.example.test/assets/profile-shared.webp", other.BackgroundImage)
|
|
referenced, err := NewR2DeleteTaskStore(conn).HasReferences(ctx, conf.Upload.ImageBucket, "profile-shared.webp")
|
|
require.NoError(t, err)
|
|
require.True(t, referenced)
|
|
referenced, err = NewR2DeleteTaskStore(conn).HasReferences(ctx, conf.Upload.ImageBucket, "default-background.webp")
|
|
require.NoError(t, err)
|
|
require.True(t, referenced)
|
|
}
|
|
|
|
func TestPurgeUserContentOutboxFailureRollsBack(t *testing.T) {
|
|
setR2TestConfig(t)
|
|
conn, _ := newTestDB(t)
|
|
ctx := context.Background()
|
|
users := NewUsersStore(conn)
|
|
owner := createOutboxTestUser(t, ctx, users, "[email protected]", "outbox-rollback")
|
|
question, err := NewQuestionsStore(conn).Create(ctx, CreateQuestionOptions{UserID: owner.ID, Content: "rollback"})
|
|
require.NoError(t, err)
|
|
image, err := NewUploadImagesStore(conn).Create(ctx, CreateUploadImageOptions{
|
|
QuestionID: question.ID, UploaderUserID: owner.ID, Key: "rollback.webp",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, conn.Migrator().DropTable(&R2DeleteTask{}))
|
|
require.Error(t, users.Deactivate(ctx, owner.ID))
|
|
|
|
require.Equal(t, int64(1), uploadImageCount(t, conn, image.ID))
|
|
var links int64
|
|
require.NoError(t, conn.WithContext(ctx).Model(&UploadImageQuestion{}).
|
|
Where("upload_image_id = ? AND question_id = ?", image.ID, question.ID).Count(&links).Error)
|
|
require.Equal(t, int64(1), links)
|
|
var questions int64
|
|
require.NoError(t, conn.WithContext(ctx).Unscoped().Model(&Question{}).Where("id = ?", question.ID).Count(&questions).Error)
|
|
require.Equal(t, int64(1), questions)
|
|
var user User
|
|
require.NoError(t, conn.WithContext(ctx).First(&user, owner.ID).Error)
|
|
require.False(t, user.DeletedAt.Valid)
|
|
}
|