from __future__ import annotations import json from http import HTTPStatus from backend.features.accounts.security import token_hash, verify_password class HubAdminHttpMixin: """Service-to-service bridge used by the data hub console (port 8766). Every handler here is reached only after `require_service_token`, so the shared `HUB_ADMIN_TOKEN` is the single trust boundary and no browser session or CSRF token is involved. The data hub still verifies the site session of the operator through `hub_session_check` before it exposes any of these results to a page. """ def _hub_body(self) -> dict: return self.read_json_body(allow_empty=True) def _hub_failure(self, exc: Exception) -> None: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) def hub_session_check(self) -> None: try: body = self._hub_body() except (ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc) return raw_token = str(body.get("session_token") or "") user = ( self.application_service.database.session_user(token_hash(raw_token)) if raw_token else None ) if not user: self.send_json({"ok": True, "authenticated": False}) return self.send_json( { "ok": True, "authenticated": True, "user": { "id": int(user["id"]), "username": str(user["username"]), "role": str(user.get("role") or "user"), "is_admin": str(user.get("role") or "user") == "admin", }, } ) def hub_session_logout(self) -> None: try: body = self._hub_body() except (ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc) return raw_token = str(body.get("session_token") or "") if raw_token: self.application_service.database.delete_session(token_hash(raw_token)) self.send_json({"ok": True}) def hub_password_check(self) -> None: try: body = self._hub_body() user_id = int(body.get("user_id") or 0) except (TypeError, ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc) return stored = self.application_service.database.user_password(user_id) verified = bool( stored and verify_password( str(body.get("password") or ""), str(stored.get("password_salt") or ""), str(stored.get("password_hash") or ""), ) ) self.send_json({"ok": True, "verified": verified}) def hub_system_status(self) -> None: service = self.application_service self.send_json({"ok": True, **service.system_status(), "users": service.admin_users()}) def hub_save_settings(self) -> None: try: result = self.application_service.save_system_settings(self._hub_body()) self.send_json({"ok": True, **result}) except (ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc) def hub_test_model(self) -> None: try: body = self._hub_body() result = self.application_service.test_system_llm_profile( str(body.get("model_id") or ""), body.get("profile") or {} ) self.send_json({"ok": True, "result": result}) except (ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc) def hub_fetch_models(self) -> None: try: body = self._hub_body() models = self.application_service.fetch_llm_models( str(body.get("base_url") or ""), str(body.get("api_key") or ""), ) self.send_json({"ok": True, "models": models}) except (ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc) def hub_members(self) -> None: service = self.application_service self.send_json( { "ok": True, "users": service.admin_users(), "membership": service.system_status()["membership"], } ) def hub_save_membership(self) -> None: try: service = self.application_service service.update_membership(self._hub_body()) self.send_json({"ok": True, "users": service.admin_users()}) except (ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc) def hub_invites(self) -> None: self.send_json({"ok": True, **self.application_service.accounts.invite_overview()}) def hub_create_invites(self) -> None: try: body = self._hub_body() accounts = self.application_service.accounts codes = accounts.generate_invite_codes( body.get("count") or 1, str(body.get("note") or ""), int(body.get("created_by") or 0), ) self.send_json({"ok": True, "created": codes, **accounts.invite_overview()}) except (ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc) def hub_revoke_invite(self) -> None: try: body = self._hub_body() accounts = self.application_service.accounts accounts.revoke_invite_code(str(body.get("code_id") or body.get("code") or "")) self.send_json({"ok": True, **accounts.invite_overview()}) except (ValueError, json.JSONDecodeError) as exc: self._hub_failure(exc)