Sessions: allow deleting memory-only ghost sessions
A session that exists only in the in-memory SessionManager — never persisted, or whose DB row was removed out-of-band — was listed by GET /api/sessions (the list is built from the in-memory manager) but 404'd on every per-session operation, so it could never be deleted. Two causes, both fixed: 1. _verify_session_owner() only consulted the DB and raised 404 when no row existed. It now falls back to the in-memory session's owner when (and only when) a session_manager is supplied and the caller actually owns the ghost. The DB row stays authoritative when present, and a ghost owned by another user still 404s, so the ownership/security model is unchanged. The new parameter defaults to None, preserving behavior for all other callers. 2. SessionManager.delete_session() only removed the in-memory entry when a DB row was found, so memory-only ghosts survived. It now drops the in-memory copy regardless and reports success when either the DB row or the in-memory entry was removed. Added tests/test_session_ghost_delete.py covering both layers, including the cross-owner 404, the unauthenticated 403, DB-row-wins precedence, and backward compatibility when no manager is passed. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -466,11 +466,17 @@ class SessionManager:
|
||||
db_session = db.query(DbSession).filter(DbSession.id == session_id).first()
|
||||
if db_session:
|
||||
db.delete(db_session)
|
||||
|
||||
# Drop the in-memory copy even when there is no DB row. A "ghost"
|
||||
# session lives only here (never persisted, or its row was removed
|
||||
# out-of-band); without this it can never be cleared and keeps
|
||||
# 404ing on every operation (issue #1044).
|
||||
removed_in_memory = self.sessions.pop(session_id, None) is not None
|
||||
|
||||
if db_session or removed_in_memory:
|
||||
# Commit the document-detach / message-delete above (a no-op when
|
||||
# the ghost had no rows) together with the session delete.
|
||||
db.commit()
|
||||
|
||||
if session_id in self.sessions:
|
||||
del self.sessions[session_id]
|
||||
|
||||
logger.info(f"Deleted session {session_id}")
|
||||
return True
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user