diff --git a/routstr/core/admin.py b/routstr/core/admin.py
index 390e834c..7198f553 100644
--- a/routstr/core/admin.py
+++ b/routstr/core/admin.py
@@ -4,7 +4,6 @@ from datetime import datetime, timezone
from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException, Query, Request
-from fastapi.responses import HTMLResponse, RedirectResponse
from pydantic import BaseModel
from sqlmodel import select
@@ -41,109 +40,6 @@ def require_admin_api(request: Request) -> None:
raise HTTPException(status_code=403, detail="Unauthorized")
-def is_admin_authenticated(request: Request) -> bool:
- auth_header = request.headers.get("Authorization")
- if auth_header and auth_header.startswith("Bearer "):
- token = auth_header.split(" ", 1)[1]
- expiry = admin_sessions.get(token)
- if expiry and expiry > int(datetime.now(timezone.utc).timestamp()):
- return True
-
- return False
-
-
-@admin_router.get(
- "/partials/balances",
- dependencies=[Depends(require_admin_api)],
- response_class=HTMLResponse,
-)
-async def partial_balances(request: Request) -> str:
- (
- balance_details,
- total_wallet_balance_sats,
- total_user_balance_sats,
- owner_balance,
- ) = await fetch_all_balances()
- # Provide JSON for client usage
- # Embed a script tag to update balanceDetails and the UI markup
- rows = "".join(
- [
- f"""
-
{detail["mint_url"].replace("https://", "").replace("http://", "")} • {detail["unit"].upper()}
-
{detail["wallet_balance"] if not detail.get("error") else "error"}
-
{detail["user_balance"] if not detail.get("error") else "-"}
-
0 else ""}">{detail["owner_balance"] if not detail.get("error") else "-"}
-
"""
- for detail in balance_details
- if detail.get("wallet_balance", 0) > 0 or detail.get("error")
- ]
- )
- return f"""
- Cashu Wallet Balance
-
- Your Balance (Total)
- {owner_balance} sats
-
-
- Total Wallet
- {total_wallet_balance_sats} sats
-
-
- User Balance
- {total_user_balance_sats} sats
-
- Your balance = Total wallet - User balance
-
-
- {rows}
-
-
- """
-
-
-@admin_router.get(
- "/partials/apikeys",
- dependencies=[Depends(require_admin_api)],
- response_class=HTMLResponse,
-)
-async def partial_apikeys(request: Request) -> str:
- async with create_session() as session:
- result = await session.exec(select(ApiKey))
- api_keys = result.all()
-
- def fmt_time(ts: int | None) -> str:
- if ts is None:
- return ""
- dt = datetime.fromtimestamp(ts, tz=timezone.utc)
- return f"{ts} ({dt.strftime('%Y-%m-%d %H:%M:%S')} UTC)"
-
- rows = "".join(
- [
- f"{key.hashed_key}{' (Child of ' + key.parent_key_hash[:8] + '...)' if key.parent_key_hash else ''} | {key.balance} | {key.total_spent} | {key.total_requests} | {key.refund_address} | {fmt_time(key.key_expiry_time)} |
"
- for key in api_keys
- ]
- )
- return f"""
- Temporary Balances
-
-
- | Hashed Key |
- Balance (mSats) |
- Total Spent (mSats) |
- Total Requests |
- Refund Address |
- Refund Time |
-
- {rows}
-
- """
-
-
@admin_router.get("/api/temporary-balances", dependencies=[Depends(require_admin_api)])
async def get_temporary_balances_api(request: Request) -> list[dict[str, object]]:
async with create_session() as session:
@@ -304,612 +200,6 @@ class WithdrawRequest(BaseModel):
unit: str = "sat"
-def login_form() -> str:
- return """
-
-
-
-
-
-
-
-
🔐 Admin Login
-
-
-
-
- """
-
-
-def setup_form() -> str:
- return """
-
-
-
-
-
-
-
-
🔧 Initial Admin Setup
-
Create a secure password for your admin dashboard.
-
-
-
-
- """
-
-
-def info(content: str) -> str:
- return f"""
-
-
-
-
-
-
-
-
- """
-
-
-def admin_auth() -> str:
- admin_pw = settings.admin_password
- if admin_pw == "":
- return setup_form()
- else:
- return login_form()
-
-
-async def dashboard(request: Request) -> str:
- return (
- f"""
-
-
-
-
- """
- + """
-
-
- """
- + """
-
- Admin Dashboard
-
-
-
-
-
-
-
-
-
-
-
-
×
-
Withdraw Balance
-
Select mint and currency:
-
-
Enter amount to withdraw:
-
-
Maximum: -
-
Your recommended balance: -
-
- ⚠️ Warning: Withdrawing more than your balance will use user funds!
-
-
-
-
-
-
-
-
-
×
-
Edit Settings (JSON)
-
Values shown as "[REDACTED]" will remain unchanged if left as-is.
-
-
-
-
-
-
-
-
-
-
-
-
×
-
Investigate Logs
-
Enter Request ID to investigate:
-
-
-
-
-
-
-
-
Withdrawal Token:
-
-
-
Save this token! It represents your withdrawn balance.
-
-
-
-
Temporary Balances
-
Loading API keys…
-
-
-
- """
- )
-
-
-@admin_router.get("/", response_class=HTMLResponse)
-async def admin(request: Request) -> RedirectResponse:
- return RedirectResponse("/")
-
-
-@admin_router.get("/logs/{request_id}", response_class=HTMLResponse)
-async def view_logs(request: Request, request_id: str) -> str:
- if not is_admin_authenticated(request):
- return admin_auth()
-
- logger.info(f"Investigating logs for request_id: {request_id}")
-
- # Search for log entries with this request_id
- log_entries = []
- logs_dir = Path("logs")
-
- if logs_dir.exists():
- # Get all log files sorted by modification time (most recent first)
- log_files = sorted(
- logs_dir.glob("*.log"), key=lambda x: x.stat().st_mtime, reverse=True
- )
-
- for log_file in log_files[:7]: # Check last 7 days of logs
- try:
- with open(log_file, "r") as f:
- for line in f:
- if request_id in line:
- try:
- # Parse JSON log entry
- log_data = json.loads(line.strip())
- log_entries.append(log_data)
- except json.JSONDecodeError:
- # If not JSON, include raw line
- log_entries.append({"raw": line.strip()})
- except Exception as e:
- logger.error(f"Error reading log file {log_file}: {e}")
-
- # Sort entries by timestamp if available
- log_entries.sort(key=lambda x: x.get("asctime", ""), reverse=False)
-
- # Format log entries for display
- formatted_logs = []
- for entry in log_entries:
- if "raw" in entry:
- formatted_logs.append(f'{entry["raw"]}
')
- else:
- # Format JSON log entry
- timestamp = entry.get("asctime", "Unknown time")
- level = entry.get("levelname", "INFO")
- message = entry.get("message", "")
- pathname = entry.get("pathname", "")
- lineno = entry.get("lineno", "")
-
- # Extract additional fields
- extra_fields = {
- k: v
- for k, v in entry.items()
- if k
- not in [
- "asctime",
- "levelname",
- "message",
- "pathname",
- "lineno",
- "name",
- "version",
- "request_id",
- ]
- }
-
- level_class = level.lower()
- formatted_entry = f"""
-
-
-
{message}
- """
-
- if extra_fields:
- formatted_entry += '"
-
- formatted_entry += "
"
- formatted_logs.append(formatted_entry)
-
- return (
- f"""
-
-
-
-
-
- """
- + f"""
-
- ← Back to Dashboard
- Log Investigation
-
- Request ID: {request_id}
-
-
- {"".join(formatted_logs) if formatted_logs else '
No log entries found for this Request ID
'}
-
-
- Found {len(log_entries)} log entries • Searched last 7 days of logs
-
-
-