fix(auth): rendre effectives l'expiration de session et la desactivation de compte
Deux protections etaient configurees sans avoir d'effet. Expiration de session app.py:73 definit PERMANENT_SESSION_LIFETIME = 3600, mais Flask n'applique cette duree qu'aux sessions marquees permanentes. Aucune occurrence de session.permanent n'existait dans app/. Le cookie emis etait donc un cookie de session navigateur, sans expiration, et le serveur ne verifiait aucune anciennete. Ajout de session.permanent juste avant login_user, apres la rotation anti-fixation. Desactivation de compte is_active_account n'etait consulte qu'au moment du login (auth.py:141). User n'ayant pas surcharge is_active, UserMixin renvoyait True en permanence. Desactiver un compte empechait donc la reconnexion mais laissait vivre la session en cours. La propriete is_active seule ne suffit pas : Flask-Login ne la consulte qu'a l'appel de login_user, jamais lors de la restauration d'une session depuis le cookie. Le verrou effectif est donc dans load_user, qui renvoie desormais None pour un compte desactive. La propriete est ajoutee malgre tout pour que login_user soit coherent avec le chargeur. load_user passe au passage de Query.get() (API heritee, avertie en SQLAlchemy 2.0) a db.session.get(), et tolere un identifiant non entier sans lever. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+16
-1
@@ -9,6 +9,21 @@ def load_user(user_id):
|
||||
|
||||
Returns the correct polymorphic subclass (Admin, Coach, Player, etc.)
|
||||
automatically because SQLAlchemy resolves the identity column.
|
||||
|
||||
Returns None for deactivated accounts so that disabling a user also
|
||||
invalidates the sessions they already hold. Flask-Login only consults
|
||||
is_active when login_user() is called, never when restoring a session
|
||||
from the cookie, so the check has to happen here.
|
||||
"""
|
||||
from app.extensions import db
|
||||
from app.models.user_model.user import User
|
||||
return User.query.get(int(user_id))
|
||||
|
||||
try:
|
||||
pk = int(user_id)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
user = db.session.get(User, pk)
|
||||
if user is None or not user.is_active_account:
|
||||
return None
|
||||
return user
|
||||
|
||||
@@ -51,6 +51,17 @@ class User(UserMixin, db.Model):
|
||||
'TeamMember', foreign_keys='TeamMember.player_id',
|
||||
backref='player_ref', lazy='dynamic')
|
||||
|
||||
# --- Flask-Login integration -------------------------------------------
|
||||
@property
|
||||
def is_active(self):
|
||||
"""Whether Flask-Login should accept this account.
|
||||
|
||||
UserMixin returns True unconditionally, which meant a deactivated
|
||||
account kept any session it already held. Binding this to
|
||||
is_active_account makes deactivation take effect on the next request.
|
||||
"""
|
||||
return bool(self.is_active_account)
|
||||
|
||||
# --- shared helper methods ---------------------------------------------
|
||||
def get_games_list(self):
|
||||
"""Return the user's games as a list."""
|
||||
|
||||
Reference in New Issue
Block a user