package user import ( "context" "testing" "time" "github.com/alicebob/miniredis/v2" "github.com/perfect-panel/server/internal/svc" "github.com/redis/go-redis/v9" ) func TestClearAllSessions_RemovesUserSessionsAndDeviceMappings(t *testing.T) { logic, redisClient, cleanup := newDeleteAccountRedisTestLogic(t) defer cleanup() mustRedisSet(t, redisClient, "auth:session_id:sid-user-1", "1001") mustRedisSet(t, redisClient, "auth:session_id:sid-user-2", "1001") mustRedisSet(t, redisClient, "auth:session_id:sid-other", "2002") mustRedisSet(t, redisClient, "auth:session_id:detail:sid-user-1", "detail") mustRedisSet(t, redisClient, "auth:session_id:detail:sid-other", "detail") mustRedisSet(t, redisClient, "auth:device_identifier:dev-user-1", "sid-user-1") mustRedisSet(t, redisClient, "auth:device_identifier:dev-user-2", "sid-user-2") mustRedisSet(t, redisClient, "auth:device_identifier:dev-other", "sid-other") mustRedisZAdd(t, redisClient, "auth:user_sessions:1001", "sid-user-3", 1) mustRedisSet(t, redisClient, "auth:session_id:sid-user-3", "1001") logic.clearAllSessions(1001) mustRedisNotExist(t, redisClient, "auth:session_id:sid-user-1") mustRedisNotExist(t, redisClient, "auth:session_id:sid-user-2") mustRedisNotExist(t, redisClient, "auth:session_id:sid-user-3") mustRedisNotExist(t, redisClient, "auth:session_id:detail:sid-user-1") mustRedisNotExist(t, redisClient, "auth:user_sessions:1001") mustRedisNotExist(t, redisClient, "auth:device_identifier:dev-user-1") mustRedisNotExist(t, redisClient, "auth:device_identifier:dev-user-2") mustRedisExist(t, redisClient, "auth:session_id:sid-other") mustRedisExist(t, redisClient, "auth:session_id:detail:sid-other") mustRedisExist(t, redisClient, "auth:device_identifier:dev-other") } func TestClearAllSessions_ScanFallbackWorksWithoutUserSessionIndex(t *testing.T) { logic, redisClient, cleanup := newDeleteAccountRedisTestLogic(t) defer cleanup() mustRedisSet(t, redisClient, "auth:session_id:sid-a", "3003") mustRedisSet(t, redisClient, "auth:session_id:sid-b", "3003") mustRedisSet(t, redisClient, "auth:session_id:sid-c", "4004") logic.clearAllSessions(3003) mustRedisNotExist(t, redisClient, "auth:session_id:sid-a") mustRedisNotExist(t, redisClient, "auth:session_id:sid-b") mustRedisExist(t, redisClient, "auth:session_id:sid-c") } func newDeleteAccountRedisTestLogic(t *testing.T) (*DeleteAccountLogic, *redis.Client, func()) { t.Helper() miniRedis := miniredis.RunT(t) redisClient := redis.NewClient(&redis.Options{Addr: miniRedis.Addr()}) logic := NewDeleteAccountLogic(context.Background(), &svc.ServiceContext{Redis: redisClient}) cleanup := func() { _ = redisClient.Close() miniRedis.Close() } return logic, redisClient, cleanup } func mustRedisSet(t *testing.T, redisClient *redis.Client, key, value string) { t.Helper() if err := redisClient.Set(context.Background(), key, value, time.Hour).Err(); err != nil { t.Fatalf("redis set %s failed: %v", key, err) } } func mustRedisZAdd(t *testing.T, redisClient *redis.Client, key, member string, score float64) { t.Helper() if err := redisClient.ZAdd(context.Background(), key, redis.Z{Member: member, Score: score}).Err(); err != nil { t.Fatalf("redis zadd %s failed: %v", key, err) } } func mustRedisExist(t *testing.T, redisClient *redis.Client, key string) { t.Helper() exists, err := redisClient.Exists(context.Background(), key).Result() if err != nil { t.Fatalf("redis exists %s failed: %v", key, err) } if exists == 0 { t.Fatalf("expected redis key %s to exist", key) } } func mustRedisNotExist(t *testing.T, redisClient *redis.Client, key string) { t.Helper() exists, err := redisClient.Exists(context.Background(), key).Result() if err != nil { t.Fatalf("redis exists %s failed: %v", key, err) } if exists != 0 { t.Fatalf("expected redis key %s to be deleted", key) } }