fix(csrf): centraliser l'injection des tokens CSRF via un dcc.Store et un callback pattern-matching
Remplace les 7 callbacks CSRF individuels (un par formulaire, avec IDs string
page-spécifiques) par un seul dcc.Store(id="csrf-token") dans le layout principal
et un callback pattern-matching Output({"type": "csrf-input", "index": ALL}).
Évite les erreurs Dash "id non trouvé dans le layout" sans recourir à
suppress_callback_exceptions=True.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+11
-14
@@ -1,7 +1,6 @@
|
||||
import dash_bootstrap_components as dbc
|
||||
from dash import Input, Output, callback, dcc, html, register_page
|
||||
from dash import dcc, html, register_page
|
||||
from flask_login import current_user
|
||||
from flask_wtf.csrf import generate_csrf
|
||||
|
||||
NAME = "Mon compte"
|
||||
|
||||
@@ -42,7 +41,11 @@ def layout(error: str | None = None, password_changed: str | None = None, **_):
|
||||
method="POST",
|
||||
action="/auth/change-password",
|
||||
children=[
|
||||
dcc.Input(type="hidden", id="csrf-change", name="csrf_token"),
|
||||
dcc.Input(
|
||||
type="hidden",
|
||||
id={"type": "csrf-input", "index": "change"},
|
||||
name="csrf_token",
|
||||
),
|
||||
dbc.Label("Mot de passe actuel"),
|
||||
dbc.Input(
|
||||
type="password",
|
||||
@@ -74,19 +77,13 @@ def layout(error: str | None = None, password_changed: str | None = None, **_):
|
||||
method="POST",
|
||||
action="/auth/logout",
|
||||
children=[
|
||||
dcc.Input(type="hidden", id="csrf-logout", name="csrf_token"),
|
||||
dcc.Input(
|
||||
type="hidden",
|
||||
id={"type": "csrf-input", "index": "logout"},
|
||||
name="csrf_token",
|
||||
),
|
||||
dbc.Button("Déconnexion", type="submit", color="secondary"),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@callback(Output("csrf-change", "value"), Input("csrf-change", "id"))
|
||||
def _fill_csrf_change(_):
|
||||
return generate_csrf()
|
||||
|
||||
|
||||
@callback(Output("csrf-logout", "value"), Input("csrf-logout", "id"))
|
||||
def _fill_csrf_logout(_):
|
||||
return generate_csrf()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import dash_bootstrap_components as dbc
|
||||
from dash import Input, Output, callback, dcc, html, register_page
|
||||
from flask_wtf.csrf import generate_csrf
|
||||
from dash import dcc, html, register_page
|
||||
|
||||
NAME = "Connexion"
|
||||
|
||||
@@ -47,7 +46,11 @@ def layout(error: str | None = None, email: str | None = None, **kwargs):
|
||||
method="POST",
|
||||
action="/auth/login",
|
||||
children=[
|
||||
dcc.Input(type="hidden", id="csrf-login", name="csrf_token"),
|
||||
dcc.Input(
|
||||
type="hidden",
|
||||
id={"type": "csrf-input", "index": "login"},
|
||||
name="csrf_token",
|
||||
),
|
||||
dcc.Input(type="hidden", name="next", value=next_url),
|
||||
dbc.Label("Adresse email"),
|
||||
dbc.Input(
|
||||
@@ -77,8 +80,3 @@ def layout(error: str | None = None, email: str | None = None, **kwargs):
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@callback(Output("csrf-login", "value"), Input("csrf-login", "id"))
|
||||
def _fill_csrf(_):
|
||||
return generate_csrf()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import dash_bootstrap_components as dbc
|
||||
from dash import Input, Output, callback, dcc, html, register_page
|
||||
from flask_wtf.csrf import generate_csrf
|
||||
from dash import dcc, html, register_page
|
||||
|
||||
NAME = "Inscription"
|
||||
|
||||
@@ -36,7 +35,11 @@ def layout(error: str | None = None, email: str | None = None, **_):
|
||||
method="POST",
|
||||
action="/auth/signup",
|
||||
children=[
|
||||
dcc.Input(type="hidden", id="csrf-signup", name="csrf_token"),
|
||||
dcc.Input(
|
||||
type="hidden",
|
||||
id={"type": "csrf-input", "index": "signup"},
|
||||
name="csrf_token",
|
||||
),
|
||||
dbc.Label("Adresse email"),
|
||||
dbc.Input(
|
||||
type="email",
|
||||
@@ -68,8 +71,3 @@ def layout(error: str | None = None, email: str | None = None, **_):
|
||||
dcc.Link("Déjà un compte ? Se connecter", href="/connexion"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@callback(Output("csrf-signup", "value"), Input("csrf-signup", "id"))
|
||||
def _fill_csrf(_):
|
||||
return generate_csrf()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import dash_bootstrap_components as dbc
|
||||
from dash import Input, Output, callback, dcc, html, register_page
|
||||
from flask_wtf.csrf import generate_csrf
|
||||
from dash import dcc, html, register_page
|
||||
|
||||
NAME = "Mot de passe oublié"
|
||||
|
||||
@@ -46,7 +45,11 @@ def layout(
|
||||
method="POST",
|
||||
action="/auth/request-password-reset",
|
||||
children=[
|
||||
dcc.Input(type="hidden", id="csrf-forgot", name="csrf_token"),
|
||||
dcc.Input(
|
||||
type="hidden",
|
||||
id={"type": "csrf-input", "index": "forgot"},
|
||||
name="csrf_token",
|
||||
),
|
||||
dbc.Label("Adresse email"),
|
||||
dbc.Input(
|
||||
type="email",
|
||||
@@ -62,8 +65,3 @@ def layout(
|
||||
dcc.Link("Retour à la connexion", href="/connexion"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@callback(Output("csrf-forgot", "value"), Input("csrf-forgot", "id"))
|
||||
def _fill_csrf(_):
|
||||
return generate_csrf()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import dash_bootstrap_components as dbc
|
||||
from dash import Input, Output, callback, dcc, html, register_page
|
||||
from flask_wtf.csrf import generate_csrf
|
||||
from dash import dcc, html, register_page
|
||||
|
||||
from src.auth.tokens import validate_password_reset_token
|
||||
|
||||
@@ -47,7 +46,11 @@ def layout(token: str | None = None, error: str | None = None, **_):
|
||||
method="POST",
|
||||
action="/auth/reset-password",
|
||||
children=[
|
||||
dcc.Input(type="hidden", id="csrf-reset", name="csrf_token"),
|
||||
dcc.Input(
|
||||
type="hidden",
|
||||
id={"type": "csrf-input", "index": "reset"},
|
||||
name="csrf_token",
|
||||
),
|
||||
dcc.Input(type="hidden", name="token", value=token),
|
||||
dbc.Label("Nouveau mot de passe (8 caractères minimum)"),
|
||||
dbc.Input(
|
||||
@@ -70,8 +73,3 @@ def layout(token: str | None = None, error: str | None = None, **_):
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@callback(Output("csrf-reset", "value"), Input("csrf-reset", "id"))
|
||||
def _fill_csrf(_):
|
||||
return generate_csrf()
|
||||
|
||||
Reference in New Issue
Block a user