| 1 | from helpers.api import ApiHandler, Request, Response |
| 2 | from helpers import dotenv |
| 3 | import models |
| 4 | |
| 5 | API_KEY_PLACEHOLDER = "************" |
| 6 | |
| 7 | |
| 8 | class ApiKeys(ApiHandler): |
| 9 | async def process(self, input: dict, request: Request) -> dict | Response: |
| 10 | action = input.get("action", "get") # get | set | reveal |
| 11 | |
| 12 | if action == "get": |
| 13 | return self._get_keys() |
| 14 | elif action == "set": |
| 15 | return self._set_keys(input) |
| 16 | elif action == "reveal": |
| 17 | return self._reveal_key(input) |
| 18 | |
| 19 | return Response(status=400, response=f"Unknown action: {action}") |
| 20 | |
| 21 | def _get_keys(self) -> dict: |
| 22 | from helpers.providers import get_providers |
| 23 | |
| 24 | providers = get_providers("chat") + get_providers("embedding") |
| 25 | seen = set() |
| 26 | keys = {} |
| 27 | |
| 28 | for p in providers: |
| 29 | pid = p.get("value", "") |
| 30 | if pid and pid not in seen: |
| 31 | seen.add(pid) |
| 32 | api_key = models.get_api_key(pid) |
| 33 | has_key = bool(api_key and api_key.strip() and api_key != "None") |
| 34 | keys[pid] = { |
| 35 | "label": p.get("label", pid), |
| 36 | "has_key": has_key, |
| 37 | "masked": API_KEY_PLACEHOLDER if has_key else "", |
| 38 | } |
| 39 | |
| 40 | return {"keys": keys} |
| 41 | |
| 42 | def _set_keys(self, input: dict) -> dict: |
| 43 | updates = input.get("keys", {}) |
| 44 | if not isinstance(updates, dict): |
| 45 | return {"ok": False, "error": "Invalid keys format"} |
| 46 | |
| 47 | for provider, value in updates.items(): |
| 48 | if isinstance(value, str) and value != API_KEY_PLACEHOLDER: |
| 49 | dotenv.save_dotenv_value(f"API_KEY_{provider.upper()}", value) |
| 50 | |
| 51 | return {"ok": True} |
| 52 | |
| 53 | def _reveal_key(self, input: dict) -> dict: |
| 54 | provider = input.get("provider", "") |
| 55 | if not provider: |
| 56 | return {"ok": False, "error": "Missing provider"} |
| 57 | api_key = models.get_api_key(provider) |
| 58 | if api_key and api_key.strip() and api_key != "None": |
| 59 | return {"ok": True, "value": api_key} |
| 60 | return {"ok": True, "value": ""} |