Add browser Python editor with Pyodide, user auth, and workspace API
- FastAPI serves static UI, file CRUD under code/ and read-only lib/ - Pyodide worker runs Python and Jedi completions in the browser - SQLite accounts: login/register, session cookies, superuser user management - Optional EDITOR_API_KEY, AUTH_* env vars, .env.example - Pipenv, pytest, Selenium smoke test, README Made-with: Cursor
This commit is contained in:
47
src/editor_app/main.py
Normal file
47
src/editor_app/main.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import os
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from editor_app.config import STATIC_DIR, WORKSPACE_ROOT
|
||||
from editor_app.db.models import Base
|
||||
from editor_app.db.session import get_engine
|
||||
from editor_app.deps import require_api_access
|
||||
from editor_app.routers.auth_routes import router as auth_router
|
||||
from editor_app.routers.files import router as files_router
|
||||
from editor_app.routers.frontend import router as frontend_router
|
||||
from editor_app.routers.users_admin import router as users_admin_router
|
||||
from editor_app.services import accounts
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_app: FastAPI):
|
||||
(WORKSPACE_ROOT / "lib").mkdir(parents=True, exist_ok=True)
|
||||
engine = get_engine()
|
||||
Base.metadata.create_all(bind=engine)
|
||||
factory = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
db = factory()
|
||||
try:
|
||||
if accounts.auth_enabled():
|
||||
bu = os.environ.get("BOOTSTRAP_ADMIN_USERNAME", "").strip()
|
||||
bp = os.environ.get("BOOTSTRAP_ADMIN_PASSWORD", "").strip()
|
||||
if bu and bp and accounts.count_users(db) == 0:
|
||||
accounts.create_user(db, bu, bp, is_superuser=True)
|
||||
finally:
|
||||
db.close()
|
||||
yield
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
|
||||
app.include_router(frontend_router)
|
||||
app.include_router(auth_router)
|
||||
app.include_router(users_admin_router)
|
||||
app.include_router(files_router, dependencies=[Depends(require_api_access)])
|
||||
return app
|
||||
|
||||
|
||||
app = create_app()
|
||||
Reference in New Issue
Block a user