added quick connect auth from jellyfin, still needs to have some more cleaning before push to prod #2
+38
-7
@@ -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,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user