feat: connected accounts + Gemini API key in account settings UI
Settings page gains two new sections: - Connected Accounts: shows linked Google email (read-only) - Gemini API Key: paste personal key from aistudio.google.com, shows masked hint of saved key, remove link to revert to server key POST /settings/gemini-key saves/clears gemini_api_key in auth.json. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,7 @@ import jwt
|
||||
from fastapi import APIRouter, Form, Request
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
|
||||
from auth_utils import COOKIE_NAME, decode_token, check_credentials, set_password
|
||||
from auth_utils import COOKIE_NAME, decode_token, check_credentials, set_password, _read_auth, _write_auth
|
||||
from persona import list_user_personas
|
||||
from config import settings as app_settings
|
||||
|
||||
@@ -41,6 +41,20 @@ def _get_session_user(request: Request) -> str | None:
|
||||
def _settings_page(username: str, personas: list[str], success: str = "", error: str = "") -> str:
|
||||
html = (_STATIC / "settings.html").read_text()
|
||||
html = html.replace("{{ username }}", username)
|
||||
|
||||
# Connected Google account
|
||||
auth_data = _read_auth(username)
|
||||
google_email = auth_data.get("google_email") or ""
|
||||
html = html.replace("{{ google_email }}", google_email)
|
||||
|
||||
# Gemini API key — show masked hint only, never the full key
|
||||
gemini_key = auth_data.get("gemini_api_key") or ""
|
||||
if gemini_key:
|
||||
hint = f"Saved (…{gemini_key[-4:]})"
|
||||
else:
|
||||
hint = "Using server key"
|
||||
html = html.replace("{{ gemini_key_hint }}", hint)
|
||||
html = html.replace("{{ gemini_key_set }}", "true" if gemini_key else "false")
|
||||
persona_items = "\n".join(
|
||||
f'''<li>
|
||||
<a href="/{username}/{p}" class="persona-link">{p}</a>
|
||||
@@ -139,6 +153,30 @@ async def rename_username(
|
||||
return resp
|
||||
|
||||
|
||||
@router.post("/settings/gemini-key", include_in_schema=False)
|
||||
async def save_gemini_key(
|
||||
request: Request,
|
||||
gemini_api_key: str = Form(...),
|
||||
):
|
||||
username = _get_session_user(request)
|
||||
if not username:
|
||||
return RedirectResponse("/login", status_code=302)
|
||||
|
||||
personas = list_user_personas(username)
|
||||
gemini_api_key = gemini_api_key.strip()
|
||||
|
||||
data = _read_auth(username)
|
||||
if gemini_api_key:
|
||||
data["gemini_api_key"] = gemini_api_key
|
||||
msg = "Gemini API key saved."
|
||||
else:
|
||||
data.pop("gemini_api_key", None)
|
||||
msg = "Gemini API key removed — using server key."
|
||||
_write_auth(username, data)
|
||||
logger.info("gemini key updated: %s", username)
|
||||
return HTMLResponse(_settings_page(username, personas, success=msg))
|
||||
|
||||
|
||||
@router.post("/settings/persona/rename", include_in_schema=False)
|
||||
async def rename_persona(
|
||||
request: Request,
|
||||
|
||||
Reference in New Issue
Block a user