From 73b48dc728bcf26c9233f69ed32e8c4815bd7359 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 10 Dec 2025 17:59:44 -0500 Subject: [PATCH] millieux de tout brisrr --- listfiles.sh | 60 ++++++++- src/auth/AuthContext.jsx | 223 +++++++++++++++++++------------ src/components/Layout/TopBar.jsx | 76 +++++++++-- 3 files changed, 256 insertions(+), 103 deletions(-) diff --git a/listfiles.sh b/listfiles.sh index 68b1127..792ffa0 100644 --- a/listfiles.sh +++ b/listfiles.sh @@ -1,5 +1,55 @@ -for f in $(find src -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.css" \) ! -name "maplibre.css"); do - echo "================== FILE: $f ==================" - cat "$f" - echo "" -done | termux-clipboard-set +#!/data/data/com.termux/files/usr/bin/bash +set -euo pipefail + +# Nombre de parties voulues +PARTS=3 + +# Fichier temporaire qui contient tout le code +TMPFILE=$(mktemp) +cleanup() { rm -f "$TMPFILE" "${TMPFILE}"_part_* 2>/dev/null || true; } +trap cleanup EXIT + +# 1) Construire le gros fichier avec tous les .js/.jsx/.css +find src -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.css" \) ! -name "maplibre.css" -print0 | +while IFS= read -r -d '' f; do + printf '================== FILE: %s ==================\n' "$f" >> "$TMPFILE" + cat "$f" >> "$TMPFILE" + printf '\n' >> "$TMPFILE" +done + +# 2) Découper en exactement PARTS morceaux (ou moins si très petit) +# -n l/3 = découpe en 3 blocs de lignes à peu près égaux +split -n l/"$PARTS" -d --additional-suffix=".txt" "$TMPFILE" "${TMPFILE}_part_" + +# 3) Envoyer chaque morceau dans le presse-papier, ENTER pour le suivant +parts=( "${TMPFILE}_part_"*.txt ) +total=${#parts[@]} + +if [ "$total" -eq 0 ]; then + echo "Aucun contenu trouvé." + exit 0 +fi + +echo "📦 Total: $total partie(s) à envoyer dans ChatGPT." + +idx=1 +for p in "${parts[@]}"; do + # On ajoute une bannière claire DEBUT/FIN pour chaque partie + { + echo "===== SOCIOWIRE FRONTEND – PART $idx / $total (BEGIN) =====" + cat "$p" + echo + echo "===== END OF SOCIOWIRE FRONTEND – PART $idx / $total =====" + } | termux-clipboard-set + + echo "➡️ Partie $idx / $total copiée dans le presse-papier." + if [ "$idx" -lt "$total" ]; then + echo "Colle cette partie dans ChatGPT, envoie le message," + echo "puis reviens ici et appuie sur ENTER pour la suivante (ou 'q' + ENTER pour quitter)…" + read -r ans || true + [ "$ans" = "q" ] || [ "$ans" = "Q" ] && break + fi + idx=$((idx+1)) +done + +echo "✅ Terminé." diff --git a/src/auth/AuthContext.jsx b/src/auth/AuthContext.jsx index 0c2d9d6..4b16782 100644 --- a/src/auth/AuthContext.jsx +++ b/src/auth/AuthContext.jsx @@ -1,105 +1,153 @@ import React, { createContext, useContext, useEffect, useState } from "react"; -import keycloak from "./keycloak"; + +// CONFIG KEYCLOAK +const KC_BASE = "https://web.sociowire.com:8443"; +const KC_REALM = "sociowire"; +const KC_CLIENT_ID = "sociowire-frontend"; + +const TOKEN_KEY = "sociowire:token"; const AuthContext = createContext(null); +function parseJwt(token) { + try { + const [, payload] = token.split("."); + const json = atob(payload.replace(/-/g, "+").replace(/_/g, "/")); + return JSON.parse(json); + } catch { + return {}; + } +} + export function AuthProvider({ children }) { - const [kc, setKc] = useState(null); - const [loading, setLoading] = useState(true); + const [token, setToken] = useState(null); const [authenticated, setAuthenticated] = useState(false); const [username, setUsername] = useState(""); + const [loading, setLoading] = useState(true); const [lastError, setLastError] = useState(""); + // charger token depuis localStorage au démarrage useEffect(() => { - let isMounted = true; - - async function init() { - try { - console.log("[AUTH] init keycloak…"); - const ok = await keycloak.init({ - onLoad: "check-sso", // ne force pas le login au chargement - checkLoginIframe: false, - }); - - if (!isMounted) return; - - console.log("[AUTH] init result:", ok); - window.kc = keycloak; // debug global - - setKc(keycloak); - setAuthenticated(ok); - - if (ok && keycloak.tokenParsed) { - const p = keycloak.tokenParsed; - const name = - p.preferred_username || - p.email || - p.name || - (p.sub ? String(p.sub) : ""); - setUsername(name || ""); - } else { - setUsername(""); - } - } catch (err) { - console.error("[AUTH] keycloak init error", err); - if (isMounted) { - setLastError(String(err)); - } - } finally { - if (isMounted) setLoading(false); - } - } - - init(); - - // refresh token simplifié - const interval = setInterval(() => { - if (!keycloak || !keycloak.authenticated) return; - keycloak - .updateToken(60) - .then((refreshed) => { - if (refreshed) { - console.log("[AUTH] token refreshed"); + try { + const saved = localStorage.getItem(TOKEN_KEY); + if (saved) { + const data = JSON.parse(saved); + if (data && data.access_token) { + const now = Date.now() / 1000; + const payload = parseJwt(data.access_token); + if (!payload.exp || payload.exp > now) { + setToken(data.access_token); + setAuthenticated(true); + const name = + payload.preferred_username || + payload.email || + payload.name || + (payload.sub ? String(payload.sub) : ""); + setUsername(name || ""); } - }) - .catch((err) => { - console.warn("[AUTH] token refresh error", err); - }); - }, 30000); - - return () => { - isMounted = false; - clearInterval(interval); - }; + } + } + } catch (e) { + console.warn("[AUTH] load token error", e); + } finally { + setLoading(false); + } }, []); - const login = () => { - keycloak.login({ - redirectUri: window.location.href, - }); + async function login(user, pass) { + setLastError(""); + if (!user || !pass) { + setLastError("Username & password required."); + return; + } + setLoading(true); + try { + const params = new URLSearchParams(); + params.set("grant_type", "password"); + params.set("client_id", KC_CLIENT_ID); + params.set("username", user); + params.set("password", pass); + + const res = await fetch( + `${KC_BASE}/realms/${KC_REALM}/protocol/openid-connect/token`, + { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: params.toString(), + } + ); + + if (!res.ok) { + const text = await res.text(); + console.error("[AUTH] login failed", res.status, text); + setLastError("Invalid credentials or auth error."); + setAuthenticated(false); + setToken(null); + setUsername(""); + try { + localStorage.removeItem(TOKEN_KEY); + } catch {} + return; + } + + const data = await res.json(); + const accessToken = data.access_token; + if (!accessToken) { + setLastError("No access token returned."); + return; + } + + const payload = parseJwt(accessToken); + const name = + payload.preferred_username || + payload.email || + payload.name || + (payload.sub ? String(payload.sub) : ""); + + setToken(accessToken); + setAuthenticated(true); + setUsername(name || ""); + setLastError(""); + + try { + localStorage.setItem(TOKEN_KEY, JSON.stringify(data)); + } catch (e) { + console.warn("[AUTH] save token error", e); + } + } catch (err) { + console.error("[AUTH] login error", err); + setLastError("Network/auth error."); + setAuthenticated(false); + setToken(null); + setUsername(""); + } finally { + setLoading(false); + } + } + + function logout() { + setToken(null); + setAuthenticated(false); + setUsername(""); + setLastError(""); + try { + localStorage.removeItem(TOKEN_KEY); + } catch {} + } + + const value = { + loading, + authenticated, + username, + token, + lastError, + login, + logout, }; - const logout = () => { - keycloak.logout({ - redirectUri: window.location.origin + "/", - }); - }; - - return ( - - {children} - - ); + return {children}; } export function useAuth() { @@ -109,3 +157,4 @@ export function useAuth() { } return ctx; } +// modif 1 \ No newline at end of file diff --git a/src/components/Layout/TopBar.jsx b/src/components/Layout/TopBar.jsx index f733643..186695e 100644 --- a/src/components/Layout/TopBar.jsx +++ b/src/components/Layout/TopBar.jsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import { useAuth } from "../../auth/AuthContext"; const THEME_LABELS = { @@ -8,12 +8,27 @@ const THEME_LABELS = { }; export default function TopBar({ theme = "dark", onChangeTheme }) { - const { loading, authenticated, username, login, logout, lastError } = useAuth(); + const { + loading, + authenticated, + username, + login, + logout, + lastError, + } = useAuth(); + + const [user, setUser] = useState(""); + const [pass, setPass] = useState(""); let authLabel = "AUTH: anon"; if (loading) authLabel = "AUTH: loading…"; else if (authenticated) authLabel = `AUTH: user=${username || "?"}`; + const handleSubmit = (e) => { + e.preventDefault(); + login(user.trim(), pass); + }; + return (
SW
@@ -25,7 +40,7 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { {authLabel} {lastError && ( - (auth err) + ({lastError}) )} @@ -48,11 +63,7 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { ))} - {loading ? ( - - ) : authenticated ? ( + {authenticated ? (
{username}
) : ( - +
+ setUser(e.target.value)} + style={{ + fontSize: "0.7rem", + padding: "0.15rem 0.4rem", + borderRadius: 999, + border: "1px solid #4b5563", + background: "#020617", + color: "#e5e7eb", + }} + /> + setPass(e.target.value)} + style={{ + fontSize: "0.7rem", + padding: "0.15rem 0.4rem", + borderRadius: 999, + border: "1px solid #4b5563", + background: "#020617", + color: "#e5e7eb", + }} + /> + +
)}
); } +// modif 2 \ No newline at end of file