feat: v4.0.1 — onboarding, landing page, smart redirect, register GET, 404 stylé, API unifiée
- Landing page / pour visiteurs non-auth (template landing.html) - Redirection / intelligente: non-auth → landing, auth sans Gitea → local workspace, auth+Gitea → dashboard - GET /auth/register — page d'inscription dédiée (tab register actif) - 404 handler stylisé thème Notion sombre (JSON pour /api/*, HTML pour le reste) - Alias /api/pages GET/POST → /board/api/pages (307 redirect) - 133 tests passent
This commit is contained in:
@@ -85,6 +85,27 @@ async function handleLogin(e){e.preventDefault();const email=document.getElement
|
||||
</html>"""
|
||||
|
||||
|
||||
@router.get("/register")
|
||||
async def register_page(request: Request):
|
||||
"""Show the registration page (local login page with register tab active)."""
|
||||
return HTMLResponse(LOCAL_LOGIN_HTML.replace(
|
||||
'class="tab active" onclick="switchTab(\'login\')"',
|
||||
'class="tab" onclick="switchTab(\'login\')"'
|
||||
).replace(
|
||||
'class="tab" onclick="switchTab(\'register\')"',
|
||||
'class="tab active" onclick="switchTab(\'register\')"'
|
||||
).replace(
|
||||
'let mode=\'login\';',
|
||||
'let mode=\'register\';'
|
||||
).replace(
|
||||
'id="name-group" style="display:none"',
|
||||
'id="name-group" style="display:block"'
|
||||
).replace(
|
||||
'id="submit-btn">Login<',
|
||||
'id="submit-btn">Register<'
|
||||
), status_code=200)
|
||||
|
||||
|
||||
@router.get("/login")
|
||||
async def login(request: Request, provider: str = Query("gitea")):
|
||||
"""Redirect to OAuth2 authorize page or show local login page."""
|
||||
|
||||
@@ -404,11 +404,29 @@ async def dashboard(
|
||||
search: str = Query(default=""),
|
||||
show_archived: bool = Query(default=False),
|
||||
):
|
||||
auth = _get_user_or_redirect(request)
|
||||
if isinstance(auth, RedirectResponse):
|
||||
return auth
|
||||
# Check if user has Gitea connected — if not, show local workspace
|
||||
user_id = auth.get("id") if isinstance(auth, dict) else 1
|
||||
"""Smart root route: landing for visitors, local workspace for new users, dashboard for Gitea users."""
|
||||
user = SessionManager.decode_session(request.cookies.get("flowdeck_session", ""))
|
||||
|
||||
# ── Not authenticated → show landing page ──
|
||||
if not user:
|
||||
# Allow through if DB is empty (fresh install)
|
||||
try:
|
||||
with get_conn() as conn:
|
||||
count = conn.execute("SELECT COUNT(*) FROM users").fetchone()[0]
|
||||
if count == 0:
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||
template = env.get_template("landing.html")
|
||||
return template.render()
|
||||
except Exception:
|
||||
pass
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||
template = env.get_template("landing.html")
|
||||
return template.render()
|
||||
|
||||
# ── Authenticated ──
|
||||
user_id = user.get("id", 1)
|
||||
has_gitea = False
|
||||
try:
|
||||
with get_conn() as conn:
|
||||
@@ -419,8 +437,9 @@ async def dashboard(
|
||||
has_gitea = bool(tok)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not has_gitea:
|
||||
# Check if user has any workspace — if not, send to workspaces
|
||||
# Check if user has any workspace
|
||||
try:
|
||||
with get_conn() as conn:
|
||||
ws_count = conn.execute(
|
||||
@@ -431,6 +450,8 @@ async def dashboard(
|
||||
except Exception:
|
||||
pass
|
||||
return RedirectResponse("/local-workspace", status_code=302)
|
||||
|
||||
# ── Gitea user → full dashboard ──
|
||||
try:
|
||||
repos = await gitea.get_user_repos(page=1, limit=50)
|
||||
if search:
|
||||
|
||||
Reference in New Issue
Block a user