Files
leggen/leggend/main.py
Elisiário Couto f0fee4fd82 fix: Implement proper GoCardless authentication and add dev features
Authentication Fixes:
- Implement proper async GoCardless token management in leggend service
- Add automatic token refresh and creation for expired/missing tokens
- Unify auth.json storage path between CLI and API (~/.config/leggen/)
- Fix 401 Unauthorized errors when accessing GoCardless API

Development Enhancements:
- Add --reload flag to leggend for automatic file watching and restart
- Add --host and --port options for flexible service binding
- Include both leggend/ and leggen/ directories in reload watching
- Improve development workflow with hot reloading

Configuration Consistency:
- Standardize config path to ~/.config/leggen/config.toml for both CLI and API
- Ensure auth.json is stored in same location as main config
- Add httpx dependency for async HTTP requests in leggend service

Verified working: leggen status command successfully authenticates
and retrieves bank/account data via leggend API service.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-09 19:39:11 +01:00

117 lines
3.0 KiB
Python

import asyncio
from contextlib import asynccontextmanager
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from loguru import logger
from leggend.api.routes import banks, accounts, sync, notifications
from leggend.background.scheduler import scheduler
from leggend.config import config
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
logger.info("Starting leggend service...")
# Load configuration
try:
config.load_config()
logger.info("Configuration loaded successfully")
except Exception as e:
logger.error(f"Failed to load configuration: {e}")
raise
# Start background scheduler
scheduler.start()
logger.info("Background scheduler started")
yield
# Shutdown
logger.info("Shutting down leggend service...")
scheduler.shutdown()
def create_app() -> FastAPI:
app = FastAPI(
title="Leggend API",
description="Open Banking API for Leggen",
version="0.6.11",
lifespan=lifespan,
)
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "http://localhost:5173"], # SvelteKit dev servers
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include API routes
app.include_router(banks.router, prefix="/api/v1", tags=["banks"])
app.include_router(accounts.router, prefix="/api/v1", tags=["accounts"])
app.include_router(sync.router, prefix="/api/v1", tags=["sync"])
app.include_router(notifications.router, prefix="/api/v1", tags=["notifications"])
@app.get("/")
async def root():
return {"message": "Leggend API is running", "version": "0.6.11"}
@app.get("/health")
async def health():
return {"status": "healthy", "config_loaded": config._config is not None}
return app
def main():
import argparse
parser = argparse.ArgumentParser(description="Start the Leggend API service")
parser.add_argument(
"--reload",
action="store_true",
help="Enable auto-reload for development"
)
parser.add_argument(
"--host",
default="0.0.0.0",
help="Host to bind to (default: 0.0.0.0)"
)
parser.add_argument(
"--port",
type=int,
default=8000,
help="Port to bind to (default: 8000)"
)
args = parser.parse_args()
if args.reload:
# Use string import for reload to work properly
uvicorn.run(
"leggend.main:create_app",
factory=True,
host=args.host,
port=args.port,
log_level="info",
access_log=True,
reload=True,
reload_dirs=["leggend", "leggen"], # Watch both directories
)
else:
app = create_app()
uvicorn.run(
app,
host=args.host,
port=args.port,
log_level="info",
access_log=True,
)
if __name__ == "__main__":
main()