from pathlib import Path from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse, RedirectResponse from pydantic import BaseModel from sqlalchemy.orm import Session from app.admin.services import AdminService from app.config import get_settings as get_app_settings from app.db import SecretORM, get_session from app.google.auth import GoogleAuthError, GoogleAuthManager from app.llm.ollama_client import OllamaClient from app.models import ( AnythingLLMStatus, AutomationRecord, GoogleIntegrationStatus, MemoryRecord, OllamaStatus, RuntimeSettings, TelegramStatus, UserProfileRecord, UserRecord, ) from app.tools.second_brain import SecondBrainTool router = APIRouter(prefix="/admin", tags=["admin"]) class SecretPayload(BaseModel): key: str value: str class GoogleClientPayload(BaseModel): client_id: str client_secret: str def get_admin_service(session: Session = Depends(get_session)) -> AdminService: return AdminService(session) def get_google_auth_manager() -> GoogleAuthManager: return GoogleAuthManager(get_app_settings(), Path(__file__).resolve().parents[2]) def sync_google_client_file(service: AdminService, manager: GoogleAuthManager) -> None: settings = get_app_settings() client_id_record = service.session.get(SecretORM, "google_client_id") client_secret_record = service.session.get(SecretORM, "google_client_secret") client_id = (client_id_record.value if client_id_record else settings.google_client_id).strip() client_secret = (client_secret_record.value if client_secret_record else settings.google_client_secret).strip() if client_id and client_secret: manager.write_client_secrets_file(client_id, client_secret) @router.get("/dashboard") def get_dashboard(service: AdminService = Depends(get_admin_service)): return service.dashboard() @router.get("/settings", response_model=RuntimeSettings) def get_runtime_settings(service: AdminService = Depends(get_admin_service)): return service.get_runtime_settings() @router.put("/settings", response_model=RuntimeSettings) def put_settings(payload: RuntimeSettings, service: AdminService = Depends(get_admin_service)): return service.update_runtime_settings(payload) @router.get("/users", response_model=list[UserRecord]) def get_users(service: AdminService = Depends(get_admin_service)): return service.list_users() @router.post("/users", response_model=UserRecord) def post_user(payload: UserRecord, service: AdminService = Depends(get_admin_service)): return service.save_user(payload) @router.get("/profiles", response_model=list[UserProfileRecord]) def get_profiles(service: AdminService = Depends(get_admin_service)): return service.list_user_profiles() @router.get("/automations", response_model=list[AutomationRecord]) def get_automations(service: AdminService = Depends(get_admin_service)): return service.list_automations() @router.get("/memory", response_model=list[MemoryRecord]) def get_memory(service: AdminService = Depends(get_admin_service)): return service.list_memory() @router.delete("/memory") def delete_memory(service: AdminService = Depends(get_admin_service)): service.clear_memory() return {"status": "ok"} @router.get("/secrets/{key}") def get_secret(key: str, service: AdminService = Depends(get_admin_service)): return {"key": key, "masked": service.get_secret_mask(key)} @router.post("/secrets") def post_secret(payload: SecretPayload, service: AdminService = Depends(get_admin_service)): service.save_secret(payload.key, payload.value) return {"status": "ok"} @router.post("/integrations/google/client") def post_google_client( payload: GoogleClientPayload, service: AdminService = Depends(get_admin_service), manager: GoogleAuthManager = Depends(get_google_auth_manager), ): service.save_secret("google_client_id", payload.client_id.strip()) service.save_secret("google_client_secret", payload.client_secret.strip()) sync_google_client_file(service, manager) return {"status": "ok"} @router.get("/integrations/llm", response_model=OllamaStatus) @router.get("/integrations/ollama", response_model=OllamaStatus) async def get_llm_status(service: AdminService = Depends(get_admin_service)): runtime = service.get_runtime_settings() settings = get_app_settings() secret = service.session.get(SecretORM, "zai_api_key") if runtime.model_provider == "zai" else None client = OllamaClient( base_url=runtime.local_base_url if runtime.model_provider == "local" else settings.zai_base_url, provider=runtime.model_provider, api_key=secret.value if secret else settings.zai_api_key, ) return await client.status(runtime.local_model if runtime.model_provider == "local" else runtime.zai_model) @router.get("/integrations/telegram", response_model=TelegramStatus) def get_telegram_status(service: AdminService = Depends(get_admin_service)): return service.telegram_status() @router.get("/integrations/anythingllm", response_model=AnythingLLMStatus) async def get_anythingllm_status(service: AdminService = Depends(get_admin_service)): runtime = service.get_runtime_settings() settings = get_app_settings() secret = service.session.get(SecretORM, "anythingllm_api_key") tool = SecondBrainTool( base_url=runtime.anythingllm_base_url, workspace_slug=runtime.anythingllm_workspace_slug, api_key=secret.value if secret else settings.anythingllm_api_key, ) status = await tool.status() return AnythingLLMStatus( reachable=bool(status.get("reachable")), workspace_found=bool(status.get("workspace_found")), base_url=runtime.anythingllm_base_url, workspace_slug=runtime.anythingllm_workspace_slug, message=str(status.get("message", "")), ) @router.get("/integrations/google", response_model=GoogleIntegrationStatus) def get_google_status( request: Request, service: AdminService = Depends(get_admin_service), manager: GoogleAuthManager = Depends(get_google_auth_manager), ): sync_google_client_file(service, manager) client_configured, connected, message = manager.oauth_status() connect_url = str(request.url_for("google_oauth_connect")) return GoogleIntegrationStatus( client_configured=client_configured, connected=connected, connect_url=connect_url, message=message, ) @router.get("/integrations/google/connect", name="google_oauth_connect") def google_oauth_connect( request: Request, service: AdminService = Depends(get_admin_service), manager: GoogleAuthManager = Depends(get_google_auth_manager), ): redirect_uri = str(request.url_for("google_oauth_callback")) try: sync_google_client_file(service, manager) authorization_url = manager.begin_web_oauth(redirect_uri) except GoogleAuthError as exc: return HTMLResponse( ( "
" f"{exc}
" "Add your client_secret.json file, then try the connect button again.
" "" ), status_code=400, ) return RedirectResponse(url=authorization_url) @router.get("/integrations/google/callback", response_class=HTMLResponse, name="google_oauth_callback") def google_oauth_callback( request: Request, state: str | None = None, error: str | None = None, manager: GoogleAuthManager = Depends(get_google_auth_manager), ): if error: return HTMLResponse( ( "" f"{error}
" "You can close this tab and try again from the WiseClaw admin panel.
" "" ), status_code=400, ) if not state: return HTMLResponse( ( "" "Missing OAuth state.
" "You can close this tab and try again from the WiseClaw admin panel.
" "" ), status_code=400, ) try: manager.complete_web_oauth(str(request.url_for("google_oauth_callback")), state, str(request.url)) except Exception as exc: return HTMLResponse( ( "" f"{exc}
" "You can close this tab and try again from the WiseClaw admin panel.
" "" ), status_code=400, ) return HTMLResponse( ( "" "WiseClaw can now use your Gmail and Google Drive tools.
" "You can close this tab and refresh the admin panel.
" "" ) )