from __future__ import annotations import time from typing import Any import httpx from flask import jsonify, g from .. import settings from ..keycloak import admin_client, require_auth, require_account_access from ..utils import random_password def register(app) -> None: @app.route("/api/account/overview", methods=["GET"]) @require_auth def account_overview() -> Any: ok, resp = require_account_access() if not ok: return resp username = g.keycloak_username keycloak_email = g.keycloak_email or "" mailu_app_password = "" if admin_client().ready() and username: try: user = admin_client().find_user(username) or {} user_id = user.get("id") or "" if user_id: full = admin_client().get_user(str(user_id)) if not keycloak_email: keycloak_email = str(full.get("email") or "") attrs = full.get("attributes") or {} if isinstance(attrs, dict): values = attrs.get("mailu_app_password") or [] if isinstance(values, list) and values: mailu_app_password = str(values[0]) except Exception: pass mailu_username = "" if keycloak_email and keycloak_email.lower().endswith(f"@{settings.MAILU_DOMAIN.lower()}"): mailu_username = keycloak_email elif username: mailu_username = f"{username}@{settings.MAILU_DOMAIN}" mailu_status = "ready" jellyfin_status = "ready" if not admin_client().ready(): mailu_status = "server not configured" jellyfin_status = "server not configured" return jsonify( { "user": {"username": username, "email": keycloak_email, "groups": g.keycloak_groups}, "mailu": {"status": mailu_status, "username": mailu_username, "app_password": mailu_app_password}, "jellyfin": {"status": jellyfin_status, "username": username}, } ) @app.route("/api/account/mailu/rotate", methods=["POST"]) @require_auth def account_mailu_rotate() -> Any: ok, resp = require_account_access() if not ok: return resp if not admin_client().ready(): return jsonify({"error": "server not configured"}), 503 username = g.keycloak_username if not username: return jsonify({"error": "missing username"}), 400 password = random_password() try: admin_client().set_user_attribute(username, "mailu_app_password", password) except Exception: return jsonify({"error": "failed to update mail password"}), 502 sync_ok = False sync_error = "" if settings.MAILU_SYNC_URL: try: with httpx.Client(timeout=30) as client: resp = client.post( settings.MAILU_SYNC_URL, json={"ts": int(time.time()), "wait": True, "reason": "portal_mailu_rotate"}, ) sync_ok = resp.status_code == 200 if not sync_ok: sync_error = f"sync status {resp.status_code}" except Exception: sync_error = "sync request failed" return jsonify({"password": password, "sync_ok": sync_ok, "sync_error": sync_error})