68 lines
2.1 KiB
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)
|
|
}
|