fix: side peek des bases repasse en vanilla JS + largeur 1100px standard (v7.49.0)
FlowDeck CI / test (push) Failing after 3h13m58s
FlowDeck CI / lint (push) Successful in 2m12s
FlowDeck CI / docker (push) Skipped

- Panneau peek: les bindings Alpine (x-data absent du conteneur) rendaient
  loovverture et le redimensionnement inoperants -> cblage direct sur le document.
- Helper unique window.fdWirePeekResize (app.js): pointer capture, 300px-90vw,
  clic=fermer, largeur persiste fd_peek_width partagee entre les 4 peeks.
- database-table-container margin:0 (tableau colle a gauche, marge Library).
- .lib-container remonte dans app.css (trash etait pleine largeur), .db-index 1100px.
- ObsiGate verifie sans code: creation .xlsx OK (openpyxl, #186).
This commit is contained in:
2026-10-05 22:47:36 -04:00
parent 894004a1f5
commit 1d1cdbd618
63 changed files with 9473 additions and 393 deletions
+13 -2
View File
@@ -11,6 +11,17 @@ from app.services.http_client import shared_client
logger = logging.getLogger(__name__)
# Valeurs de substitution livrées dans app/config.py : elles sont NON VIDES,
# donc un simple `bool(client_id and client_secret)` les considérait comme
# configurées et /auth/login redirigeait vers Gitea avec client_id=test-id
# (échec d'authentification garanti). Un placeholder == provider non configuré.
_PLACEHOLDER_CREDS = {"test-id", "test-secret", "change-me", "changeme", "your-client-id"}
def _real(value: str | None) -> bool:
"""True when ``value`` is a real credential (not empty, not a placeholder)."""
return bool(value) and value.strip().lower() not in _PLACEHOLDER_CREDS
class OAuthProvider(ABC):
"""Abstract OAuth2 provider interface."""
@@ -52,7 +63,7 @@ class GiteaProvider(OAuthProvider):
self.redirect_uri = redirect_uri
def is_enabled(self) -> bool:
return bool(self.client_id and self.client_secret)
return _real(self.client_id) and _real(self.client_secret)
def get_authorize_url(self, state: str, redirect_uri: str | None = None, force_login: bool = False) -> str:
params = {
@@ -144,7 +155,7 @@ class GitHubProvider(OAuthProvider):
self.api_url = "https://api.github.com"
def is_enabled(self) -> bool:
return bool(self.client_id and self.client_secret)
return _real(self.client_id) and _real(self.client_secret)
def get_authorize_url(self, state: str, redirect_uri: str | None = None, force_login: bool = False) -> str:
return (
+15 -2
View File
@@ -13,6 +13,19 @@ logger = logging.getLogger(__name__)
_serializer = URLSafeTimedSerializer(settings.app_secret_key)
# Colonnes de la table ``users`` qui ne doivent JAMAIS quitter le serveur :
# le cookie de session est signé (HMAC) mais pas chiffré — son payload est
# lisible en base64 par quiconque détient le cookie, et ``/auth/user`` le
# renvoyait tel quel au client.
_SECRET_USER_FIELDS = ("password_hash",)
def public_user(user_data: dict | None) -> dict | None:
"""Return a copy of ``user_data`` stripped of credential material."""
if user_data is None:
return None
return {k: v for k, v in user_data.items() if k not in _SECRET_USER_FIELDS}
class SessionManager:
"""Manages user sessions via signed cookies (v5.2.0: revocable).
@@ -30,7 +43,7 @@ class SessionManager:
``user_sessions`` table (ip + user agent) and becomes revocable.
"""
payload = {
"user": user_data,
"user": public_user(user_data),
"created_at": datetime.now(UTC).replace(tzinfo=None).isoformat(),
}
user_id = user_data.get("id")
@@ -93,7 +106,7 @@ class SessionManager:
"""Re-sign a cookie keeping its session id (used after profile edits)."""
sid = SessionManager.session_id(cookie) if cookie else None
payload = {
"user": user_data,
"user": public_user(user_data),
"created_at": datetime.now(UTC).replace(tzinfo=None).isoformat(),
}
user_id = user_data.get("id")