From d46fd51aa098e88ef455d79e21df6939a54ddeb0 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Wed, 12 Nov 2025 15:31:06 +0100 Subject: [PATCH 1/2] added reset of TTL for login tokens when user is active --- src/baby_monitor/repositories/token/memory_token.py | 10 +++++++++- src/baby_monitor/repositories/token/redis_token.py | 8 +++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/baby_monitor/repositories/token/memory_token.py b/src/baby_monitor/repositories/token/memory_token.py index 968247f..409c076 100644 --- a/src/baby_monitor/repositories/token/memory_token.py +++ b/src/baby_monitor/repositories/token/memory_token.py @@ -16,6 +16,7 @@ class InMemoryTokenRepository(TokenRepositoryInterface): def __init__(self) -> None: # token -> (user_id, expiry_time) self._tokens: dict[str, tuple[int, datetime]] = {} + self._default_ttl = 3600 # Store default TTL for sliding expiration def store(self, token: str, user_id: int, ttl: int = 3600) -> None: """Store a token with TTL (time to live in seconds).""" @@ -23,7 +24,10 @@ class InMemoryTokenRepository(TokenRepositoryInterface): self._tokens[token] = (user_id, expiry) def verify(self, token: str) -> int | None: - """Verify token and return user_id if valid, None otherwise.""" + """Verify token and return user_id if valid, None otherwise. + + Implements sliding expiration: extends token lifetime on each verification. + """ if token not in self._tokens: return None @@ -34,6 +38,10 @@ class InMemoryTokenRepository(TokenRepositoryInterface): del self._tokens[token] return None + # Sliding expiration: extend the token lifetime + new_expiry = datetime.now(UTC) + timedelta(seconds=self._default_ttl) + self._tokens[token] = (user_id, new_expiry) + return user_id def invalidate(self, token: str) -> None: diff --git a/src/baby_monitor/repositories/token/redis_token.py b/src/baby_monitor/repositories/token/redis_token.py index 6e9a364..52abda5 100644 --- a/src/baby_monitor/repositories/token/redis_token.py +++ b/src/baby_monitor/repositories/token/redis_token.py @@ -21,6 +21,7 @@ class RedisTokenRepository(TokenRepositoryInterface): redis_client: Redis client instance from redis.from_url() """ self.redis = redis_client + self.default_ttl = 3600 # Store default TTL for sliding expiration def store(self, token: str, user_id: int, ttl: int = 3600) -> None: """Store a token with TTL (time to live in seconds).""" @@ -28,10 +29,15 @@ class RedisTokenRepository(TokenRepositoryInterface): self.redis.setex(key, ttl, str(user_id)) def verify(self, token: str) -> int | None: - """Verify token and return user_id if valid, None otherwise.""" + """Verify token and return user_id if valid, None otherwise. + + Implements sliding expiration: extends token lifetime on verification. + """ key = f"token:{token}" user_id_str = self.redis.get(key) if user_id_str: + # Sliding expiration: extend the token lifetime + self.redis.expire(key, self.default_ttl) return int(user_id_str) return None From a302dc51c6533d131d653e58eeb152f8308908b6 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Wed, 12 Nov 2025 15:34:10 +0100 Subject: [PATCH 2/2] CQ fixes --- src/baby_monitor/repositories/token/memory_token.py | 2 +- src/baby_monitor/repositories/token/redis_token.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/baby_monitor/repositories/token/memory_token.py b/src/baby_monitor/repositories/token/memory_token.py index 409c076..735ff4d 100644 --- a/src/baby_monitor/repositories/token/memory_token.py +++ b/src/baby_monitor/repositories/token/memory_token.py @@ -25,7 +25,7 @@ class InMemoryTokenRepository(TokenRepositoryInterface): def verify(self, token: str) -> int | None: """Verify token and return user_id if valid, None otherwise. - + Implements sliding expiration: extends token lifetime on each verification. """ if token not in self._tokens: diff --git a/src/baby_monitor/repositories/token/redis_token.py b/src/baby_monitor/repositories/token/redis_token.py index 52abda5..044c8dd 100644 --- a/src/baby_monitor/repositories/token/redis_token.py +++ b/src/baby_monitor/repositories/token/redis_token.py @@ -30,7 +30,7 @@ class RedisTokenRepository(TokenRepositoryInterface): def verify(self, token: str) -> int | None: """Verify token and return user_id if valid, None otherwise. - + Implements sliding expiration: extends token lifetime on verification. """ key = f"token:{token}"