Un jeton par appareil, révocable seul (2.2.0)

Tous les appareils partageaient le jeton du serveur : perdre un téléphone
obligeait à changer ce jeton, donc à réappairer tout le monde. Chaque
appairage émet désormais le sien.

Révoquer devient une opération locale, vérifiée en appairant deux appareils
puis en coupant le premier : 401 pour lui, 200 pour l'autre, jeton maître
intact. L'interface du serveur les liste avec leur modèle, leur date
d'appairage et leur dernière synchronisation — sans jamais afficher les jetons
eux-mêmes, ce qui reviendrait à les distribuer.

La table s'ajoute sans toucher aux données existantes et le jeton maître reste
accepté : rien ne casse pour un appareil appairé avant cette version.
This commit is contained in:
tuxgyver committed 2026-09-13 21:23:19 +02:00
1 parent 51b60cda70
commit 28cb545685
7 files changed
+130 -8

No files matched your search

+41
View File
@@ -42,6 +42,15 @@ CREATE TABLE IF NOT EXISTS media (
);
CREATE INDEX IF NOT EXISTS media_updated ON media(updated_at);
CREATE TABLE IF NOT EXISTS devices (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
token TEXT NOT NULL UNIQUE,
created_at INTEGER NOT NULL,
last_seen INTEGER
);
CREATE INDEX IF NOT EXISTS devices_token ON devices(token);
CREATE TABLE IF NOT EXISTS watches (
id TEXT PRIMARY KEY,
query TEXT NOT NULL,
@@ -150,6 +159,38 @@ class Storage:
self._db.commit()
return item
# --- Appareils ------------------------------------------------------
def add_device(self, name: str, token: str) -> str:
device_id = uuid.uuid4().hex
self._db.execute(
"INSERT INTO devices (id,name,token,created_at) VALUES (?,?,?,?)",
(device_id, name.strip() or "Appareil", token, now()),
)
self._db.commit()
return device_id
def device_by_token(self, token: str) -> dict | None:
row = self._db.execute("SELECT * FROM devices WHERE token = ?", (token,)).fetchone()
return dict(row) if row else None
def touch_device(self, device_id: str) -> None:
"""Dernière utilisation : c'est ce qui permet de reconnaître un appareil oublié."""
self._db.execute("UPDATE devices SET last_seen = ? WHERE id = ?", (now(), device_id))
self._db.commit()
def devices(self) -> list[dict]:
return [
# Le jeton n'est jamais renvoyé : le lister reviendrait à le distribuer.
{k: v for k, v in dict(row).items() if k != "token"}
for row in self._db.execute("SELECT * FROM devices ORDER BY created_at DESC")
]
def delete_device(self, device_id: str) -> bool:
cursor = self._db.execute("DELETE FROM devices WHERE id = ?", (device_id,))
self._db.commit()
return cursor.rowcount > 0
# --- Guets ----------------------------------------------------------
def add_watch(self, query: str) -> str: