v0.3.0: OAuth2, CSRF, rate limiting, issue CRUD, webhooks, card detail, checklists
- OAuth2 Gitea (login/callback/logout) with fallback admin mode
- Session management with signed cookies (itsdangerous, 7 days)
- CSRF protection middleware on all POST/PUT/PATCH/DELETE
- Rate limiting in-memory (60 req/min per IP)
- Issue creation from FlowDeck (POST /api/issues/{owner}/{repo})
- Inline issue editing (PATCH /api/issues/{owner}/{repo}/{issue_id})
- Card detail modal (double-click): description, labels, comments
- Checklists with toggleable items (CRUD endpoints + UI)
- Priority + due date editable on cards
- Webhook receiver (POST /api/webhook) with HMAC-SHA256
- Auto-register/status webhooks for repos
- GiteaClient: create_issue, update_issue, get_comments, webhooks, collaborators
- New DB tables: users, user_tokens, checklists, checklist_items
- CSS: modal, forms, checklists, comments, PR section
This commit is contained in:
+28
-4
@@ -6,10 +6,13 @@ import logging
|
||||
from fastapi import FastAPI
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from starlette.middleware.sessions import SessionMiddleware
|
||||
|
||||
from app.config import settings
|
||||
from app.db import init_db
|
||||
from app.routers import dashboard, board, notes, api
|
||||
from app.middleware.csrf import CSRFMiddleware
|
||||
from app.routers import dashboard, board, notes, api, auth, webhooks
|
||||
from app.services.gitea_client import gitea
|
||||
|
||||
# ── logging ──
|
||||
|
||||
@@ -23,12 +26,24 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
app = FastAPI(
|
||||
title="FlowDeck",
|
||||
version="0.2.0",
|
||||
version="0.3.0",
|
||||
docs_url="/docs" if settings.log_level == "DEBUG" else None,
|
||||
redoc_url=None,
|
||||
)
|
||||
|
||||
# ponytail: CORS for LAN access
|
||||
# ── middleware (order matters) ──
|
||||
|
||||
# Session (for OAuth2 state)
|
||||
app.add_middleware(
|
||||
SessionMiddleware,
|
||||
secret_key=settings.app_secret_key,
|
||||
max_age=3600, # 1 hour for OAuth state
|
||||
)
|
||||
|
||||
# CSRF protection
|
||||
app.add_middleware(CSRFMiddleware)
|
||||
|
||||
# CORS for LAN access
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
@@ -38,10 +53,12 @@ app.add_middleware(
|
||||
|
||||
# ── routers ──
|
||||
|
||||
app.include_router(auth.router)
|
||||
app.include_router(dashboard.router)
|
||||
app.include_router(board.router)
|
||||
app.include_router(notes.router)
|
||||
app.include_router(api.router)
|
||||
app.include_router(webhooks.router)
|
||||
|
||||
# ── static ──
|
||||
|
||||
@@ -51,4 +68,11 @@ app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||
@app.on_event("startup")
|
||||
async def startup():
|
||||
init_db()
|
||||
logger.info("FlowDeck started on port %d", settings.app_port)
|
||||
# Seed admin user for non-OAuth mode
|
||||
from app.db import get_conn
|
||||
with get_conn() as conn:
|
||||
conn.execute(
|
||||
"INSERT OR IGNORE INTO users (login, full_name, email, is_admin) VALUES ('admin', 'Admin', '', 1)"
|
||||
)
|
||||
conn.commit()
|
||||
logger.info("FlowDeck v0.3.0 started on port %d", settings.app_port)
|
||||
|
||||
Reference in New Issue
Block a user