Files

38 lines
1.2 KiB
Python
Raw Permalink Normal View History

2026-09-13 19:59:54 +01:00
"""Auth helpers and decorators."""
from functools import wraps
from flask import abort, redirect, url_for, session, flash, request
from flask_login import current_user
def admin_required(view):
@wraps(view)
def wrapped(*args, **kwargs):
if not current_user.is_authenticated:
return redirect(url_for("auth.login", next=request.full_path))
if not current_user.is_admin:
abort(403)
if session.get("mfa_pending"):
return redirect(url_for("auth.mfa_challenge"))
return view(*args, **kwargs)
return wrapped
def login_required_full(view):
"""Like flask_login.login_required, but also blocks users with pending MFA."""
@wraps(view)
def wrapped(*args, **kwargs):
if not current_user.is_authenticated:
return redirect(url_for("auth.login", next=request.full_path))
if session.get("mfa_pending"):
return redirect(url_for("auth.mfa_challenge"))
return view(*args, **kwargs)
return wrapped
def get_remote_ip() -> str:
"""Best-effort IP detection for audit logs."""
fwd = request.headers.get("X-Forwarded-For", "")
if fwd:
return fwd.split(",")[0].strip()
return request.remote_addr or ""