Public Access
des modifications spécifiques sur les droits des utilisateurs
Build and Push Docker Image / build-and-push (push) Successful in 36s
Build and Push Docker Image / build-and-push (push) Successful in 36s
This commit is contained in:
1 parent
e82a23988b
commit
21348c70aa
8 files changed
+2094
-41
No files matched your search
@@ -0,0 +1,238 @@
|
||||
[1mdiff --git a/main.py b/main.py[m
|
||||
[1mindex 6115ef5..30b8c0c 100644[m
|
||||
[1m--- a/main.py[m
|
||||
[1m+++ b/main.py[m
|
||||
[36m@@ -8,11 +8,10 @@[m [mfrom fasthtml.common import *[m
|
||||
from starlette.staticfiles import StaticFiles[m
|
||||
from starlette.responses import FileResponse, Response, HTMLResponse, RedirectResponse[m
|
||||
from starlette.middleware.base import BaseHTTPMiddleware[m
|
||||
[31m-from modules.user_db import load_users, save_users, changer_nom_utilisateur, mettre_a_jour_mot_de_passe[m
|
||||
[31m-from modules.system_utils import obtenir_infos_serveur[m
|
||||
[32m+[m
|
||||
from modules.theme import get_theme_hdrs[m
|
||||
from modules.database import nettoyer_vieilles_discussions, HISTORY_FILE, load_history, save_history[m
|
||||
[31m-from modules.ui_components import render_main_page, render_sidebar, render_login_page, render_rag_upload_modal[m
|
||||
[32m+[m[32mfrom modules.ui_components import render_main_page, render_sidebar, render_login_page, render_rag_upload_modal, render_backoffice_page[m
|
||||
from modules.chat_handler import handle_chat_request[m
|
||||
from modules.security import verifier_et_bloquer_vpn, journaliser_ip[m
|
||||
from modules.auth_manager import IDENTIFIANTS_ADMIN, verifier_mot_de_passe[m
|
||||
[36m@@ -20,6 +19,8 @@[m [mfrom modules.logger import log_event[m
|
||||
from modules.billing_manager import charger_soldes, sauvegarder_soldes[m
|
||||
from modules.rag_manager import auto_apprendre_rag[m
|
||||
from modules.vector_rag import indexer_dossier_thematique[m
|
||||
[32m+[m[32mfrom modules.user_db import load_users, save_users, changer_nom_utilisateur, mettre_a_jour_mot_de_passe[m
|
||||
[32m+[m[32mfrom modules.system_utils import obtenir_infos_serveur[m
|
||||
[m
|
||||
# Lancement du module d'auto-mise à jour en arrière-plan[m
|
||||
import modules.model_updater[m
|
||||
[36m@@ -27,108 +28,13 @@[m [mimport modules.model_updater[m
|
||||
dossier_media = "/DATA/AppData/MULTI-IA-AETHAS38/RAG/Media"[m
|
||||
os.makedirs(dossier_media, exist_ok=True)[m
|
||||
[m
|
||||
[31m-@rt('/backoffice')[m
|
||||
[31m-def get(session, request):[m
|
||||
[31m- utilisateur = session.get('user') or request.cookies.get('aethas_user')[m
|
||||
[31m- if not utilisateur:[m
|
||||
[31m- return RedirectResponse('/login', status_code=303)[m
|
||||
[31m- [m
|
||||
[31m- users = load_users()[m
|
||||
[31m- infos_user = users.get(utilisateur, {"role": "Membre"})[m
|
||||
[31m- role = infos_user.get("role", "Membre")[m
|
||||
[31m- [m
|
||||
[31m- # Données spécifiques Super Admin[m
|
||||
[31m- stats_serveur = obtenir_infos_serveur() if role == "Super Admin" else None[m
|
||||
[31m- [m
|
||||
[31m- return render_backoffice_page(utilisateur, role, users, stats_serveur)[m
|
||||
[31m-[m
|
||||
[31m-@rt('/backoffice/update_profile')[m
|
||||
[31m-async def post(request, session):[m
|
||||
[31m- utilisateur = session.get('user') or request.cookies.get('aethas_user')[m
|
||||
[31m- if not utilisateur:[m
|
||||
[31m- return RedirectResponse('/login', status_code=303)[m
|
||||
[31m- [m
|
||||
[31m- form = await request.form()[m
|
||||
[31m- nouveau_pseudo = form.get("nouveau_pseudo")[m
|
||||
[31m- nouveau_mdp = form.get("nouveau_mdp")[m
|
||||
[31m- [m
|
||||
[31m- if nouveau_pseudo and nouveau_pseudo != utilisateur:[m
|
||||
[31m- succes = changer_nom_utilisateur(utilisateur, nouveau_pseudo)[m
|
||||
[31m- if succes:[m
|
||||
[31m- session['user'] = nouveau_pseudo[m
|
||||
[31m- resp = RedirectResponse('/backoffice', status_code=303)[m
|
||||
[31m- resp.set_cookie("aethas_user", nouveau_pseudo, max_age=86400)[m
|
||||
[31m- return resp[m
|
||||
[31m- [m
|
||||
[31m- if nouveau_mdp:[m
|
||||
[31m- mettre_a_jour_mot_de_passe(utilisateur, nouveau_mdp)[m
|
||||
[31m- [m
|
||||
[31m- return RedirectResponse('/backoffice', status_code=303)[m
|
||||
[31m-[m
|
||||
[31m-# --- WIDGET PAYPAL (RECHARGE DE CRÉDITS) ---[m
|
||||
[31m-def render_paypal_recharge_widget(montant_usd: float = 10.00):[m
|
||||
[31m- client_id = os.getenv("PAYPAL_CLIENT_ID", "test")[m
|
||||
[31m- [m
|
||||
[31m- script_paypal = Script(src=f"https://www.paypal.com/sdk/js?client-id={client_id}¤cy=USD")[m
|
||||
[31m- container_id = f"paypal-button-container-{str(montant_usd).replace('.', '')}"[m
|
||||
[31m- [m
|
||||
[31m- script_logique = Script(f"""[m
|
||||
[31m- function chargerBoutonPayPal() {{[m
|
||||
[31m- if (typeof paypal !== 'undefined') {{[m
|
||||
[31m- paypal.Buttons({{[m
|
||||
[31m- style: {{ layout: 'vertical', height: 35, shape: 'rect', label: 'paypal' }},[m
|
||||
[31m- createOrder: function(data, actions) {{[m
|
||||
[31m- return actions.order.create({{[m
|
||||
[31m- purchase_units: [{{ amount: {{ value: '{montant_usd}' }} }}][m
|
||||
[31m- }});[m
|
||||
[31m- }},[m
|
||||
[31m- onApprove: function(data, actions) {{[m
|
||||
[31m- return actions.order.capture().then(function(details) {{[m
|
||||
[31m- alert('Paiement validé par ' + details.payer.name.given_name + ' ! Vos crédits vont être ajoutés.');[m
|
||||
[31m- [m
|
||||
[31m- fetch('/api/paypal/success', {{[m
|
||||
[31m- method: 'POST',[m
|
||||
[31m- headers: {{ 'Content-Type': 'application/json' }},[m
|
||||
[31m- body: JSON.stringify({{ orderID: data.orderID }})[m
|
||||
[31m- }}).then(res => {{[m
|
||||
[31m- if(res.ok) {{[m
|
||||
[31m- document.getElementById('modal-recharge-paypal').style.display = 'none';[m
|
||||
[31m- window.location.reload();[m
|
||||
[31m- }} else {{[m
|
||||
[31m- alert("Erreur lors de la validation serveur.");[m
|
||||
[31m- }}[m
|
||||
[31m- }});[m
|
||||
[31m- }});[m
|
||||
[31m- }}[m
|
||||
[31m- }}).render('#{container_id}');[m
|
||||
[31m- }} else {{[m
|
||||
[31m- setTimeout(chargerBoutonPayPal, 100);[m
|
||||
[31m- }}[m
|
||||
[31m- }}[m
|
||||
[31m- chargerBoutonPayPal();[m
|
||||
[31m- """)[m
|
||||
[31m-[m
|
||||
[31m- paypal_box = Div([m
|
||||
[31m- H4(f"Recharge : {montant_usd} $", style="color: #fff; margin: 0 0 10px 0; font-size: 1.1em; text-align: center;"),[m
|
||||
[31m- Div(id=container_id, style="min-height: 100px; width: 100%;"),[m
|
||||
[31m- Button("Annuler", type="button", onclick="document.getElementById('modal-recharge-paypal').style.display='none'", [m
|
||||
[31m- style="background: transparent; border: 1px solid #555; color: #aaa; width: 100%; margin-top: 5px; padding: 6px; border-radius: 6px; font-size: 0.85em; cursor: pointer;"),[m
|
||||
[31m- style="background: #1a1a1a; padding: 20px; border-radius: 10px; border: 1px solid #333; width: 320px; max-width: 90vw; box-shadow: 0 8px 24px rgba(0,0,0,0.9);"[m
|
||||
[31m- )[m
|
||||
[31m-[m
|
||||
[31m- modal_overlay = Div([m
|
||||
[31m- script_paypal, paypal_box, script_logique,[m
|
||||
[31m- id="modal-recharge-paypal",[m
|
||||
[31m- style="display: none; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.6); backdrop-filter: blur(3px); align-items: center; justify-content: center; z-index: 10000;"[m
|
||||
[31m- )[m
|
||||
[31m- return modal_overlay[m
|
||||
[31m-[m
|
||||
# --- MIDDLEWARE DE SÉCURITÉ & SERVEUR MÉDIA UNIFIÉ ---[m
|
||||
class SecurityMiddleware(BaseHTTPMiddleware):[m
|
||||
async def dispatch(self, request, call_next):[m
|
||||
ip = request.headers.get("X-Forwarded-For", request.client.host).split(",")[0].strip()[m
|
||||
utilisateur = request.cookies.get("aethas_user", "visiteur")[m
|
||||
[m
|
||||
[32m+[m[32m # --- LECTURE EN RAM ULTRA-DIRECTE PAR LE MIDDLEWARE ---[m
|
||||
if request.url.path.startswith("/Media/"):[m
|
||||
fname = request.url.path.replace("/Media/", "", 1)[m
|
||||
chemin = os.path.join(dossier_media, fname)[m
|
||||
[36m@@ -140,10 +46,12 @@[m [mclass SecurityMiddleware(BaseHTTPMiddleware):[m
|
||||
return HTMLResponse(f"Erreur : {e}", status_code=500)[m
|
||||
return HTMLResponse("Fichier introuvable", status_code=404)[m
|
||||
[m
|
||||
[32m+[m[32m # EXCLUSION DE /Media POUR NE PAS BLOQUER LE RESTE[m
|
||||
if not request.url.path.startswith(("/Logo", "/login", "/Media")):[m
|
||||
if verifier_et_bloquer_vpn(ip, utilisateur):[m
|
||||
return HTMLResponse("<h1 style='color:red; text-align:center;'>Accès refusé</h1><p style='text-align:center;'>VPN ou Proxy strictement interdit.</p>", status_code=403)[m
|
||||
[m
|
||||
[32m+[m[32m # Exclusion stricte du spam de logs (Silence pour /ping et /favicon)[m
|
||||
if request.url.path not in ["/ping", "/favicon.ico"]:[m
|
||||
journaliser_ip(ip, f"Accès à {request.url.path}")[m
|
||||
[m
|
||||
[36m@@ -182,6 +90,44 @@[m [mdef get(session):[m
|
||||
resp.delete_cookie("aethas_user")[m
|
||||
return resp[m
|
||||
[m
|
||||
[32m+[m[32m# --- ROUTES DU BACK OFFICE & PROFIL ---[m
|
||||
[32m+[m[32m@rt('/backoffice')[m
|
||||
[32m+[m[32mdef get(session, request):[m
|
||||
[32m+[m[32m utilisateur = session.get('user') or request.cookies.get('aethas_user')[m
|
||||
[32m+[m[32m if not utilisateur:[m
|
||||
[32m+[m[32m return RedirectResponse('/login', status_code=303)[m
|
||||
[32m+[m[41m [m
|
||||
[32m+[m[32m users = load_users()[m
|
||||
[32m+[m[32m infos_user = users.get(utilisateur, {"role": "Membre"})[m
|
||||
[32m+[m[32m role = infos_user.get("role", "Membre")[m
|
||||
[32m+[m[41m [m
|
||||
[32m+[m[32m stats_serveur = obtenir_infos_serveur() if role == "Super Admin" else None[m
|
||||
[32m+[m[41m [m
|
||||
[32m+[m[32m return render_backoffice_page(utilisateur, role, users, stats_serveur)[m
|
||||
[32m+[m
|
||||
[32m+[m[32m@rt('/backoffice/update_profile')[m
|
||||
[32m+[m[32masync def post(request, session):[m
|
||||
[32m+[m[32m utilisateur = session.get('user') or request.cookies.get('aethas_user')[m
|
||||
[32m+[m[32m if not utilisateur:[m
|
||||
[32m+[m[32m return RedirectResponse('/login', status_code=303)[m
|
||||
[32m+[m[41m [m
|
||||
[32m+[m[32m form = await request.form()[m
|
||||
[32m+[m[32m nouveau_pseudo = form.get("nouveau_pseudo")[m
|
||||
[32m+[m[32m nouveau_mdp = form.get("nouveau_mdp")[m
|
||||
[32m+[m[41m [m
|
||||
[32m+[m[32m if nouveau_pseudo and nouveau_pseudo != utilisateur:[m
|
||||
[32m+[m[32m succes = changer_nom_utilisateur(utilisateur, nouveau_pseudo)[m
|
||||
[32m+[m[32m if succes:[m
|
||||
[32m+[m[32m session['user'] = nouveau_pseudo[m
|
||||
[32m+[m[32m resp = RedirectResponse('/backoffice', status_code=303)[m
|
||||
[32m+[m[32m resp.set_cookie("aethas_user", nouveau_pseudo, max_age=86400)[m
|
||||
[32m+[m[32m return resp[m
|
||||
[32m+[m[41m [m
|
||||
[32m+[m[32m if nouveau_mdp:[m
|
||||
[32m+[m[32m mettre_a_jour_mot_de_passe(utilisateur, nouveau_mdp)[m
|
||||
[32m+[m[41m [m
|
||||
[32m+[m[32m return RedirectResponse('/backoffice', status_code=303)[m
|
||||
[32m+[m
|
||||
# --- ROUTES PROTÉGÉES ---[m
|
||||
@rt('/')[m
|
||||
def get(session, request):[m
|
||||
[36m@@ -192,11 +138,7 @@[m [mdef get(session, request):[m
|
||||
session['user'] = utilisateur[m
|
||||
if 'current_chat_id' not in session or not session['current_chat_id']:[m
|
||||
session['current_chat_id'] = str(uuid.uuid4())[m
|
||||
[31m- [m
|
||||
[31m- main_page = render_main_page(session['current_chat_id'], utilisateur_nom=session['user'])[m
|
||||
[31m- paypal_modal = render_paypal_recharge_widget(10.00)[m
|
||||
[31m- [m
|
||||
[31m- return paypal_modal, main_page[m
|
||||
[32m+[m[32m return render_main_page(session['current_chat_id'], utilisateur_nom=session['user'])[m
|
||||
[m
|
||||
@rt('/chat')[m
|
||||
async def post(request, session):[m
|
||||
[36m@@ -245,18 +187,14 @@[m [mdef post(cid: str):[m
|
||||
if cid_str in h: del h[cid_str]; save_history(h)[m
|
||||
return render_sidebar()[m
|
||||
[m
|
||||
[31m-@rt('/api/paypal/success')[m
|
||||
[31m-async def post(request):[m
|
||||
[31m- data = await request.json()[m
|
||||
[31m- order_id = data.get("orderID")[m
|
||||
[31m- log_event("INFO", "FINANCE", f"Recharge PayPal validée - OrderID: {order_id}")[m
|
||||
[31m- return {"status": "success"}[m
|
||||
[31m-[m
|
||||
[32m+[m[32m# --- NOUVELLE ROUTE POUR LE RAG (BOUTON MANUEL) ---[m
|
||||
@rt('/api/forcer_rag')[m
|
||||
def post(prompt: str, reponse: str, theme: str):[m
|
||||
[32m+[m[32m """Intercepte la demande manuelle, lance l'indexation et renvoie un badge vert."""[m
|
||||
auto_apprendre_rag(prompt, reponse, theme)[m
|
||||
return Span("✅ Indexé", cls="msg-action-btn", style="background-color: #4caf50; color: white; border: none; cursor: default;")[m
|
||||
[m
|
||||
[32m+[m[32m# --- NOUVELLES ROUTES POUR L'UPLOAD MODAL DU RAG ---[m
|
||||
@rt('/admin/rag_modal')[m
|
||||
def get(session):[m
|
||||
if session.get('user', '') != 'xavier': [m
|
||||
[36m@@ -295,6 +233,7 @@[m [masync def post(request, session):[m
|
||||
[m
|
||||
from modules.export_utils import generer_export_comptable[m
|
||||
[m
|
||||
[32m+[m[32m# --- NOUVELLE ROUTE POUR L'EXPORT COMPTABLE EXCEL ---[m
|
||||
@rt('/admin/export_comptable')[m
|
||||
def get(session):[m
|
||||
if session.get('user', '') != 'xavier': [m
|
||||
Reference in new issue
Block a user