feat: account deletion

This commit is contained in:
juancwu 2026-05-17 15:01:04 +00:00
commit 2db260f849
20 changed files with 785 additions and 29 deletions

View file

@ -0,0 +1,30 @@
package model
import "time"
const (
AccountDeletionStatusPending = "pending"
AccountDeletionStatusProcessing = "processing"
AccountDeletionStatusCompleted = "completed"
AccountDeletionStatusFailed = "failed"
)
// AccountDeletionRequest is both the work queue entry and the historical
// audit record for an account deletion. The row is created when the user
// confirms deletion, transitions through processing, and is kept after
// completion as the audit trail (the related user row is gone by then).
type AccountDeletionRequest struct {
ID string `db:"id"`
UserID string `db:"user_id"`
Email string `db:"email"`
Name *string `db:"name"`
Reason *string `db:"reason"`
IPAddress *string `db:"ip_address"`
Status string `db:"status"`
Attempts int `db:"attempts"`
LastError *string `db:"last_error"`
SpacesDeleted *int `db:"spaces_deleted"`
RequestedAt time.Time `db:"requested_at"`
UpdatedAt time.Time `db:"updated_at"`
CompletedAt *time.Time `db:"completed_at"`
}

View file

@ -7,11 +7,16 @@ type User struct {
Email string `db:"email"`
Name *string `db:"name"`
// Allow null for passwordless users
PasswordHash *string `db:"password_hash"`
PendingEmail *string `db:"pending_email"`
EmailVerifiedAt *time.Time `db:"email_verified_at"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
PasswordHash *string `db:"password_hash"`
PendingEmail *string `db:"pending_email"`
EmailVerifiedAt *time.Time `db:"email_verified_at"`
PendingDeletionAt *time.Time `db:"pending_deletion_at"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
func (u *User) IsPendingDeletion() bool {
return u.PendingDeletionAt != nil
}
func (u *User) HasPassword() bool {