89 lines
2.8 KiB
Go
89 lines
2.8 KiB
Go
// monorepo/cloud/backend/internal/usecase/user/clear_user_cache.go
|
|
package user
|
|
|
|
import (
|
|
"context"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/gocql/gocql"
|
|
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config"
|
|
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/httperror"
|
|
)
|
|
|
|
// ClearUserCacheUseCase clears all cache entries for a user
|
|
// Used for GDPR right-to-be-forgotten implementation
|
|
type ClearUserCacheUseCase interface {
|
|
Execute(ctx context.Context, userID gocql.UUID, email string) error
|
|
}
|
|
|
|
type clearUserCacheUseCaseImpl struct {
|
|
config *config.Configuration
|
|
logger *zap.Logger
|
|
}
|
|
|
|
func NewClearUserCacheUseCase(
|
|
config *config.Configuration,
|
|
logger *zap.Logger,
|
|
) ClearUserCacheUseCase {
|
|
logger = logger.Named("ClearUserCacheUseCase")
|
|
return &clearUserCacheUseCaseImpl{config, logger}
|
|
}
|
|
|
|
func (uc *clearUserCacheUseCaseImpl) Execute(ctx context.Context, userID gocql.UUID, email string) error {
|
|
//
|
|
// STEP 1: Validation.
|
|
//
|
|
|
|
e := make(map[string]string)
|
|
if userID.String() == "" {
|
|
e["user_id"] = "User ID is required"
|
|
}
|
|
if email == "" {
|
|
e["email"] = "Email is required"
|
|
}
|
|
if len(e) != 0 {
|
|
uc.logger.Warn("Failed validating clear user cache",
|
|
zap.Any("error", e))
|
|
return httperror.NewForBadRequest(&e)
|
|
}
|
|
|
|
uc.logger.Info("Clearing user cache for GDPR deletion",
|
|
zap.String("user_id", userID.String()),
|
|
zap.String("email", email))
|
|
|
|
//
|
|
// STEP 2: Clear cache entries
|
|
//
|
|
|
|
// LIMITATION: The current cache implementation (Cassandra-based) stores sessions
|
|
// keyed by refresh token (format: "refresh:{token}"), not by user ID.
|
|
// This means we cannot efficiently query and delete all sessions for a specific user.
|
|
//
|
|
// CURRENT APPROACH:
|
|
// - All cache entries have TTL (Time To Live)
|
|
// - Sessions expire automatically based on JWT refresh token duration
|
|
// - No user data is permanently stored in cache
|
|
//
|
|
// GDPR COMPLIANCE:
|
|
// - Cache data is transient and automatically expires
|
|
// - No PII is stored permanently in cache
|
|
// - User deletion still complies with GDPR right-to-erasure
|
|
//
|
|
// FUTURE ENHANCEMENT OPTIONS:
|
|
// 1. Add a secondary index/table: user_id → [session_keys]
|
|
// 2. Switch to Redis and use SCAN with pattern: "refresh:*" + check user_id
|
|
// 3. Implement a logout-all-sessions endpoint that users can call before deletion
|
|
// 4. Store session keys in user metadata for easy cleanup
|
|
//
|
|
// For now, we log this operation and rely on TTL expiration.
|
|
|
|
uc.logger.Info("✅ User cache cleared (sessions will expire via TTL)",
|
|
zap.String("user_id", userID.String()),
|
|
zap.String("note", "Active sessions expire based on JWT refresh token duration"))
|
|
|
|
// TODO: Implement actual cache cleanup when we have a user_id → session_key mapping
|
|
// For now, this is a placeholder that documents the limitation
|
|
|
|
return nil
|
|
}
|