mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-04-20 16:40:29 +00:00
307 lines
8.6 KiB
Go
307 lines
8.6 KiB
Go
package db
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestDeleteUserDataFull_DeletesAllData(t *testing.T) {
|
|
db, err := InitDB(":memory:", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to init database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
// Create test user
|
|
testUser := &User{
|
|
DID: "did:plc:test123",
|
|
Handle: "test.bsky.social",
|
|
PDSEndpoint: "https://bsky.social",
|
|
LastSeen: time.Now(),
|
|
}
|
|
if err := UpsertUser(db, testUser); err != nil {
|
|
t.Fatalf("Failed to create user: %v", err)
|
|
}
|
|
|
|
// Create manifest
|
|
_, err = db.Exec(`
|
|
INSERT INTO manifests (did, repository, digest, hold_endpoint, schema_version, media_type, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
`, testUser.DID, "myapp", "sha256:abc123", "did:web:hold.example.com", 2,
|
|
"application/vnd.oci.image.manifest.v1+json", time.Now())
|
|
if err != nil {
|
|
t.Fatalf("Failed to create manifest: %v", err)
|
|
}
|
|
|
|
// Create tag
|
|
_, err = db.Exec(`
|
|
INSERT INTO tags (did, repository, tag, digest, created_at)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
`, testUser.DID, "myapp", "latest", "sha256:abc123", time.Now())
|
|
if err != nil {
|
|
t.Fatalf("Failed to create tag: %v", err)
|
|
}
|
|
|
|
// Create hold membership data (non-cascading)
|
|
_, err = db.Exec(`
|
|
INSERT INTO hold_crew_approvals (hold_did, user_did, approved_at, expires_at)
|
|
VALUES (?, ?, ?, ?)
|
|
`, "did:web:hold.example.com", testUser.DID, time.Now(), time.Now().Add(24*time.Hour))
|
|
if err != nil {
|
|
t.Fatalf("Failed to create crew approval: %v", err)
|
|
}
|
|
|
|
_, err = db.Exec(`
|
|
INSERT INTO hold_crew_members (hold_did, member_did, rkey, permissions)
|
|
VALUES (?, ?, ?, ?)
|
|
`, "did:web:hold.example.com", testUser.DID, "member1", `["blob:read","blob:write"]`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create crew member: %v", err)
|
|
}
|
|
|
|
// Create OAuth store
|
|
oauthStore := NewOAuthStore(db)
|
|
|
|
// Delete all user data
|
|
err = DeleteUserDataFull(db, oauthStore, testUser.DID)
|
|
if err != nil {
|
|
t.Fatalf("DeleteUserDataFull failed: %v", err)
|
|
}
|
|
|
|
// Verify user was deleted
|
|
var count int
|
|
err = db.QueryRow("SELECT COUNT(*) FROM users WHERE did = ?", testUser.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query users: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Error("Expected user to be deleted")
|
|
}
|
|
|
|
// Verify manifests were cascade deleted
|
|
err = db.QueryRow("SELECT COUNT(*) FROM manifests WHERE did = ?", testUser.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query manifests: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Error("Expected manifests to be cascade deleted")
|
|
}
|
|
|
|
// Verify tags were cascade deleted
|
|
err = db.QueryRow("SELECT COUNT(*) FROM tags WHERE did = ?", testUser.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query tags: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Error("Expected tags to be cascade deleted")
|
|
}
|
|
|
|
// Verify hold membership data was deleted
|
|
err = db.QueryRow("SELECT COUNT(*) FROM hold_crew_approvals WHERE user_did = ?", testUser.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query crew approvals: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Error("Expected crew approvals to be deleted")
|
|
}
|
|
|
|
err = db.QueryRow("SELECT COUNT(*) FROM hold_crew_members WHERE member_did = ?", testUser.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query crew members: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Error("Expected crew members to be deleted")
|
|
}
|
|
}
|
|
|
|
func TestDeleteUserDataFull_DoesNotAffectOtherUsers(t *testing.T) {
|
|
db, err := InitDB(":memory:", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to init database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
// Create two users
|
|
user1 := &User{
|
|
DID: "did:plc:user1",
|
|
Handle: "user1.bsky.social",
|
|
PDSEndpoint: "https://bsky.social",
|
|
LastSeen: time.Now(),
|
|
}
|
|
user2 := &User{
|
|
DID: "did:plc:user2",
|
|
Handle: "user2.bsky.social",
|
|
PDSEndpoint: "https://bsky.social",
|
|
LastSeen: time.Now(),
|
|
}
|
|
if err := UpsertUser(db, user1); err != nil {
|
|
t.Fatalf("Failed to create user1: %v", err)
|
|
}
|
|
if err := UpsertUser(db, user2); err != nil {
|
|
t.Fatalf("Failed to create user2: %v", err)
|
|
}
|
|
|
|
// Create manifests for both users
|
|
for _, user := range []*User{user1, user2} {
|
|
_, err = db.Exec(`
|
|
INSERT INTO manifests (did, repository, digest, hold_endpoint, schema_version, media_type, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
`, user.DID, "myapp", "sha256:"+user.DID, "did:web:hold.example.com", 2,
|
|
"application/vnd.oci.image.manifest.v1+json", time.Now())
|
|
if err != nil {
|
|
t.Fatalf("Failed to create manifest for %s: %v", user.Handle, err)
|
|
}
|
|
}
|
|
|
|
// Create hold membership data for both users
|
|
for i, user := range []*User{user1, user2} {
|
|
_, err = db.Exec(`
|
|
INSERT INTO hold_crew_members (hold_did, member_did, rkey, permissions)
|
|
VALUES (?, ?, ?, ?)
|
|
`, "did:web:hold.example.com", user.DID, fmt.Sprintf("member%d", i+1), `["blob:read"]`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create crew member for %s: %v", user.Handle, err)
|
|
}
|
|
}
|
|
|
|
oauthStore := NewOAuthStore(db)
|
|
|
|
// Delete only user1's data
|
|
err = DeleteUserDataFull(db, oauthStore, user1.DID)
|
|
if err != nil {
|
|
t.Fatalf("DeleteUserDataFull failed: %v", err)
|
|
}
|
|
|
|
// Verify user1 was deleted
|
|
var count int
|
|
err = db.QueryRow("SELECT COUNT(*) FROM users WHERE did = ?", user1.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query users: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Error("Expected user1 to be deleted")
|
|
}
|
|
|
|
// Verify user2 still exists
|
|
err = db.QueryRow("SELECT COUNT(*) FROM users WHERE did = ?", user2.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query users: %v", err)
|
|
}
|
|
if count != 1 {
|
|
t.Error("Expected user2 to still exist")
|
|
}
|
|
|
|
// Verify user2's manifests still exist
|
|
err = db.QueryRow("SELECT COUNT(*) FROM manifests WHERE did = ?", user2.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query manifests: %v", err)
|
|
}
|
|
if count != 1 {
|
|
t.Error("Expected user2's manifest to still exist")
|
|
}
|
|
|
|
// Verify user2's crew membership still exists
|
|
err = db.QueryRow("SELECT COUNT(*) FROM hold_crew_members WHERE member_did = ?", user2.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query crew members: %v", err)
|
|
}
|
|
if count != 1 {
|
|
t.Error("Expected user2's crew membership to still exist")
|
|
}
|
|
}
|
|
|
|
func TestDeleteUserDataFull_HandlesNonExistentUser(t *testing.T) {
|
|
db, err := InitDB(":memory:", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to init database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
oauthStore := NewOAuthStore(db)
|
|
|
|
// Try to delete non-existent user - should not error
|
|
err = DeleteUserDataFull(db, oauthStore, "did:plc:nonexistent")
|
|
if err != nil {
|
|
t.Errorf("Expected no error for non-existent user, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDeleteUserDataFull_WithNilOAuthStore(t *testing.T) {
|
|
db, err := InitDB(":memory:", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to init database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
testUser := &User{
|
|
DID: "did:plc:test123",
|
|
Handle: "test.bsky.social",
|
|
PDSEndpoint: "https://bsky.social",
|
|
LastSeen: time.Now(),
|
|
}
|
|
if err := UpsertUser(db, testUser); err != nil {
|
|
t.Fatalf("Failed to create user: %v", err)
|
|
}
|
|
|
|
// Delete with nil OAuth store - should still work
|
|
err = DeleteUserDataFull(db, nil, testUser.DID)
|
|
if err != nil {
|
|
t.Errorf("Expected no error with nil OAuth store, got: %v", err)
|
|
}
|
|
|
|
// Verify user was deleted
|
|
var count int
|
|
err = db.QueryRow("SELECT COUNT(*) FROM users WHERE did = ?", testUser.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query users: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Error("Expected user to be deleted")
|
|
}
|
|
}
|
|
|
|
func TestDeleteUserDataFull_DeletesDenials(t *testing.T) {
|
|
db, err := InitDB(":memory:", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("Failed to init database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
testUser := &User{
|
|
DID: "did:plc:test123",
|
|
Handle: "test.bsky.social",
|
|
PDSEndpoint: "https://bsky.social",
|
|
LastSeen: time.Now(),
|
|
}
|
|
if err := UpsertUser(db, testUser); err != nil {
|
|
t.Fatalf("Failed to create user: %v", err)
|
|
}
|
|
|
|
// Create denial record
|
|
_, err = db.Exec(`
|
|
INSERT INTO hold_crew_denials (hold_did, user_did, denial_count, next_retry_at, last_denied_at)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
`, "did:web:hold.example.com", testUser.DID, 1, time.Now().Add(24*time.Hour), time.Now())
|
|
if err != nil {
|
|
t.Fatalf("Failed to create crew denial: %v", err)
|
|
}
|
|
|
|
oauthStore := NewOAuthStore(db)
|
|
|
|
err = DeleteUserDataFull(db, oauthStore, testUser.DID)
|
|
if err != nil {
|
|
t.Fatalf("DeleteUserDataFull failed: %v", err)
|
|
}
|
|
|
|
// Verify denial was deleted
|
|
var count int
|
|
err = db.QueryRow("SELECT COUNT(*) FROM hold_crew_denials WHERE user_did = ?", testUser.DID).Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("Failed to query crew denials: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Error("Expected crew denials to be deleted")
|
|
}
|
|
}
|