monorepo/cloud/maplefile-backend/internal/repo/user/delete.go

68 lines
2.1 KiB
Go

// codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/repo/user/delete.go
package user
import (
"context"
"fmt"
"github.com/gocql/gocql"
"go.uber.org/zap"
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/validation"
)
func (impl userStorerImpl) DeleteByID(ctx context.Context, id gocql.UUID) error {
// First, get the user to know all the data we need to delete
user, err := impl.GetByID(ctx, id)
if err != nil {
return fmt.Errorf("failed to get user for deletion: %w", err)
}
if user == nil {
return nil // User doesn't exist, nothing to delete
}
batch := impl.session.NewBatch(gocql.LoggedBatch).WithContext(ctx)
// Delete from all user tables
batch.Query(`DELETE FROM users_by_id WHERE id = ?`, id)
batch.Query(`DELETE FROM users_by_email WHERE email = ?`, user.Email)
// Delete from verification code table if user has verification code
// Note: We delete by scanning since verification_code is the partition key
// This is acceptable for GDPR deletion (rare operation, thorough cleanup)
if user.SecurityData != nil && user.SecurityData.Code != "" {
batch.Query(`DELETE FROM users_by_verification_code WHERE verification_code = ?`, user.SecurityData.Code)
}
// Delete all user sessions
// Note: sessions_by_user_id is partitioned by user_id, so this is efficient
batch.Query(`DELETE FROM sessions_by_user_id WHERE user_id = ?`, id)
// Execute the batch
if err := impl.session.ExecuteBatch(batch); err != nil {
impl.logger.Error("Failed to delete user",
zap.String("user_id", id.String()),
zap.Error(err))
return fmt.Errorf("failed to delete user: %w", err)
}
impl.logger.Info("User deleted successfully",
zap.String("user_id", id.String()),
zap.String("email", validation.MaskEmail(user.Email)))
return nil
}
func (impl userStorerImpl) DeleteByEmail(ctx context.Context, email string) error {
// First get the user by email to get the ID
user, err := impl.GetByEmail(ctx, email)
if err != nil {
return fmt.Errorf("failed to get user by email for deletion: %w", err)
}
if user == nil {
return nil // User doesn't exist
}
// Delete by ID
return impl.DeleteByID(ctx, user.ID)
}