enhance auth status endpoint to return detailed linked services for Discord users

This commit is contained in:
2026-05-25 11:12:49 +02:00
parent bf358f7248
commit 51e099acdd
2 changed files with 80 additions and 7 deletions
+38 -7
View File
@@ -152,16 +152,47 @@ async def login_submit(request: Request):
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# GET /auth/status — check which services are linked # GET /auth/status — get all linked services for a Discord user
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@router.get("/status") @router.get("/Discord/status")
async def auth_status(discord_id: int): async def auth_status(discord_id: int):
"""Return which services this Discord user has linked.""" """
services: dict[str, bool] = {} Return all services linked to this Discord user with full details.
for svc_name in list_auth_services():
services[svc_name] = auth_store.is_authenticated(discord_id, svc_name) Response:
return {"discord_id": discord_id, "services": services} {
"discord_id": 123456789,
"linked_services": {
"jellyfin": {
"external_user_id": "abc123",
"external_name": "Tim",
"linked_at": "2026-05-25T10:00:00",
"credentials": {
"token": "jwt...",
"url": "http://jellyfin:8096",
"user_id": "abc123"
}
}
}
}
"""
auths = auth_store.get_all_auths(discord_id)
linked_services: dict[str, dict] = {}
for auth in auths:
svc_name = auth["service"]
linked_services[svc_name] = {
"external_user_id": auth["external_user_id"],
"external_name": auth["external_name"],
"linked_at": auth["linked_at"],
"credentials": auth["credentials"],
}
return {
"discord_id": discord_id,
"linked_services": linked_services,
}
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
+42
View File
@@ -298,6 +298,48 @@ def revoke(discord_user_id: int, service: str) -> None:
logger.info("Revoked auth for user %s on %s", discord_user_id, service) logger.info("Revoked auth for user %s on %s", discord_user_id, service)
def get_all_auths(discord_user_id: int) -> list[dict]:
"""
Return all active auth records for a Discord user.
Each record includes service name, external user id, external name,
linked_at timestamp, and the raw credentials (e.g. Jellyfin token + URL).
Used by the /api/v1/auth/status endpoint so other services can discover
linked accounts for a given Discord ID.
"""
_ensure_schema()
import json
with _db_lock:
conn = _get_conn()
rows = conn.execute(
"""SELECT service, external_user_id, external_name, credentials, linked_at
FROM user_auth
WHERE discord_user_id = ? AND is_active = 1
ORDER BY linked_at DESC""",
(discord_user_id,),
).fetchall()
conn.close()
results: list[dict] = []
for row in rows:
creds = {}
if row["credentials"]:
try:
creds = json.loads(row["credentials"])
except (json.JSONDecodeError, TypeError):
creds = {}
results.append({
"service": row["service"],
"external_user_id": row["external_user_id"] or "",
"external_name": row["external_name"] or "",
"linked_at": row["linked_at"] or "",
"credentials": creds,
})
return results
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Dev / testing — reset the entire store # Dev / testing — reset the entire store
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------