From e9d1c32b4f395fabac950cf05a6466b8771f320d Mon Sep 17 00:00:00 2001 From: bruno Date: Mon, 13 Jul 2026 15:17:17 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20Gitea=20=E2=80=94=20register,=20setting?= =?UTF-8?q?s=20connect,=20tabs=20org,=20search?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Pas de Gitea sans config: _require_gitea() β†’ 401 si pas de token OAuth 2. Register Gitea: boutons "Login/Register with Gitea" dynamiques selon l'onglet 3. Settings β†’ Integrations: βœ… Active / πŸ”— Connect / Disconnect + API status/disconnect 4. Workspaces: tabs par org (All | org1 | org2) + barre recherche πŸ” filtrage live 5. API: GET /api/gitea/status, DELETE /api/gitea/disconnect --- app/routers/auth.py | 7 +-- app/routers/gitea.py | 31 +++++++++-- app/templates/settings.html | 29 ++++++++++- app/templates/workspaces.html | 96 +++++++++++++++++++++++++---------- 4 files changed, 128 insertions(+), 35 deletions(-) diff --git a/app/routers/auth.py b/app/routers/auth.py index 58b956d..8983141 100644 --- a/app/routers/auth.py +++ b/app/routers/auth.py @@ -70,13 +70,14 @@ body{background:#191919;color:#fff;font-family:-apple-system,BlinkMacSystemFont,
- - +

Or continue with

+ +
diff --git a/app/routers/gitea.py b/app/routers/gitea.py index efa7bc0..3ff7698 100644 --- a/app/routers/gitea.py +++ b/app/routers/gitea.py @@ -6,12 +6,11 @@ router = APIRouter(tags=["gitea"], prefix="/api/gitea") def _require_gitea(request: Request): - """Return a per-user GiteaClient or fallback to admin token.""" - from app.services.gitea_client import get_user_gitea_client, GiteaClient + """Return a per-user GiteaClient or raise 401.""" + from app.services.gitea_client import get_user_gitea_client client = get_user_gitea_client(request) if not client: - # Fallback to server admin token - client = GiteaClient() + raise HTTPException(status_code=401, detail="Gitea not connected. Go to Settings β†’ Integrations or register with Gitea.") return client @@ -129,3 +128,27 @@ async def get_labels(request: Request, owner: str, repo: str): ]} except Exception as e: return JSONResponse({"error": str(e)}, status_code=502) + + +# ── Account linking ── + +@router.get("/status") +async def gitea_status(request: Request): + """Check if the current user has Gitea linked.""" + from app.services.gitea_client import get_user_gitea_client + client = get_user_gitea_client(request) + return {"linked": client is not None} + + +@router.delete("/disconnect") +async def disconnect_gitea(request: Request): + """Remove all Gitea OAuth tokens for the current user.""" + from app.auth.session import SessionManager + from app.db import get_conn + user = SessionManager.decode_session(request.cookies.get("flowdeck_session", "")) + if not user: + return JSONResponse({"error": "Not authenticated"}, status_code=401) + with get_conn() as conn: + conn.execute("DELETE FROM user_oauth_tokens WHERE user_id=? AND provider='gitea'", (user["id"],)) + conn.commit() + return {"status": "ok"} diff --git a/app/templates/settings.html b/app/templates/settings.html index 588a161..65b3791 100644 --- a/app/templates/settings.html +++ b/app/templates/settings.html @@ -318,9 +318,16 @@
Gitea
-
Connected to git.dracodev.net
+
+ Connected to git.dracodev.net + Connect your Gitea account to access projects +
+
+
+ βœ… Active + + πŸ”— Connect
-
βœ… Active
@@ -502,6 +509,8 @@ document.addEventListener('alpine:init', function() { defaultView: localStorage.getItem('fd_default_view') || 'tree', userInfo: {full_name: '{{ user.full_name or "" }}', login: '{{ user.login or "" }}', email: '{{ user.email or "" }}'}, userIsAdmin: {{ 'true' if user.get('is_admin') else 'false' }}, + // Gitea + giteaLinked: false, // Account form accountForm: {login:'{{ user.login or "" }}', full_name:'{{ user.full_name or "" }}', email:'{{ user.email or "" }}', password:''}, accountSaving: false, @@ -518,6 +527,7 @@ document.addEventListener('alpine:init', function() { async init() { await this.loadTags(); + await this.loadGiteaStatus(); }, async loadTags() { @@ -716,6 +726,21 @@ document.addEventListener('alpine:init', function() { saveDefaultView() { localStorage.setItem('fd_default_view', this.defaultView); } + async loadGiteaStatus() { + try { + var r = await fetch('/api/gitea/status'); + var d = await r.json(); + this.giteaLinked = d.linked || false; + } catch(e) { this.giteaLinked = false; } + }, + + async disconnectGitea() { + if (!confirm('Disconnect Gitea? You can reconnect anytime.')) return; + try { + var r = await fetch('/api/gitea/disconnect', { method: 'DELETE', headers: {'X-CSRF-Token': this.getCsrfToken()} }); + if (r.ok) { this.giteaLinked = false; } + } catch(e) {} + }, }; }); }); diff --git a/app/templates/workspaces.html b/app/templates/workspaces.html index b486970..5c9a7f4 100644 --- a/app/templates/workspaces.html +++ b/app/templates/workspaces.html @@ -63,6 +63,12 @@ .btn-new:hover{background:var(--bg-tertiary);color:var(--text);} .btn-sm{padding:4px 8px;font-size:11px;border-radius:6px;border:1px solid var(--border);background:transparent;color:var(--text-dim);cursor:pointer;} .btn-sm:hover{background:var(--bg-tertiary);color:var(--text);} +/* Org tabs */ +.org-tab{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:6px;font-size:13px;color:var(--text-dim);background:transparent;border:1px solid var(--border);cursor:pointer;white-space:nowrap;transition:all 100ms;} +.org-tab:hover{background:var(--bg-tertiary);color:var(--text);} +.org-tab.active{background:var(--accent);color:#fff;border-color:var(--accent);} +.org-tab-badge{font-size:10px;padding:0 5px;border-radius:8px;background:rgba(255,255,255,.15);} +.search-input:focus{border-color:var(--accent);}
@@ -98,7 +104,9 @@
Connect your Gitea account to see your projects.
- πŸ”— Login with Gitea + πŸ”— Connect Gitea + or + πŸ“ Register with Gitea
@@ -110,35 +118,57 @@
- -