From 2dbff20818d171242a15e3567e14292c0d63aea2 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Thu, 15 Oct 2026 14:24:35 +0200 Subject: fix(hub): a phone's poll secret ends with the account's sessions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The secret a phone polls /v1/push/poll with is a credential of its own, outside any session, and it outlived the ones that should have ended it: "sign out everywhere" — what someone who lost a phone presses — a passphrase change and an admin revocation left every push row in place, so the lost phone went on reading "X posted in " lines. Each now deletes the account's rows, as a reset and an erasure already did, and the poll refuses a revoked or deleted account whatever deleted the row or not. A suspended one still reads: the line telling it so is one of them. A phone still in hand is not affected for long: a refused poll makes it forget the row, and the page registers it again at its next start. Co-Authored-By: Claude Opus 5.5 --- packages/meshbay-hub/src/meshbay_hub/api/revocation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'packages/meshbay-hub/src/meshbay_hub/api/revocation.py') diff --git a/packages/meshbay-hub/src/meshbay_hub/api/revocation.py b/packages/meshbay-hub/src/meshbay_hub/api/revocation.py index c03d582..501b263 100644 --- a/packages/meshbay-hub/src/meshbay_hub/api/revocation.py +++ b/packages/meshbay-hub/src/meshbay_hub/api/revocation.py @@ -36,13 +36,13 @@ import jwt from fastapi import APIRouter, Depends, HTTPException, Request, WebSocket, WebSocketDisconnect from meshbay_common.background import spawn from pydantic import BaseModel -from sqlalchemy import select, update +from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession from meshbay_hub.api.deps import get_current_user, node_token_key_linked, require_admin from meshbay_hub.auth import decode_access_token from meshbay_hub.db.engine import get_db -from meshbay_hub.db.models import Group, GroupMember, IPLog, Node, User +from meshbay_hub.db.models import Group, GroupMember, IPLog, Node, PushSubscription, User log = logging.getLogger(__name__) @@ -667,6 +667,8 @@ async def admin_revoke( if not obj: raise HTTPException(status_code=404, detail="User not found") obj.status = "revoked" + # Its phones stop hearing anything: a poll secret is not a session. + await db.execute(delete(PushSubscription).where(PushSubscription.user_id == obj.id)) else: obj = await db.get(Group, body.target_id) if not obj: -- cgit v1.2.3