feat(auth,dashboard): 2FA mobile session persistence and sparkline cards

- Persist 2FA state in sessionStorage to survive mobile page reloads
- Reuse existing valid OTP on re-login to avoid rate limiting and duplicate emails
- Add embedded sparkline charts to SolduriCompactCard with expand toggle
- Mobile dashboard redesigned: 2 pages with enriched compact cards + cashflow type
- Login UI simplified: remove gradient bg, subtitle, icon; use design tokens
- Focus OTP input when session is restored from 2FA state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-02-26 14:36:22 +00:00
parent cbcd5fe8e7
commit 06cbf8fb9d
13 changed files with 654 additions and 248 deletions

View File

@@ -406,34 +406,45 @@ def create_auth_router(
# Pas 4: Dacă are email → trimitem OTP (2FA)
if user_email:
code = await create_otp(user_email, actual_username, login_data.server_id)
# Check for existing valid OTP (mobile page reload scenario)
existing_entry = get_otp_entry(user_email)
if code is None:
# Rate limited
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Prea multe cereri de cod. Așteptați 10 minute și încercați din nou."
if existing_entry:
# OTP already exists and is valid — skip generation and email
logger.info(
f"[2FA] Reusing existing OTP for {user_email[:3]}*** "
f"(user='{actual_username}', skipping email)"
)
else:
# Generate new OTP
code = await create_otp(user_email, actual_username, login_data.server_id)
# Trimitem emailul
try:
from backend.modules.telegram.utils.email_service import get_email_service
email_service = get_email_service()
email_sent = await email_service.send_auth_code(user_email, code, actual_username)
if not email_sent:
logger.error(f"[2FA] Failed to send OTP email to {user_email[:3]}***")
if code is None:
# Rate limited
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Nu s-a putut trimite codul de verificare. Încercați din nou."
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Prea multe cereri de cod. Așteptați 10 minute și încercați din nou."
)
logger.info(f"[2FA] OTP sent to {user_email[:3]}*** for user '{actual_username}'")
# Trimitem emailul
try:
from backend.modules.telegram.utils.email_service import get_email_service
email_service = get_email_service()
email_sent = await email_service.send_auth_code(user_email, code, actual_username)
except ImportError:
# Email service nu e disponibil — fallback la login direct
logger.warning("[2FA] Email service not available, falling back to direct login")
user_email = None
if not email_sent:
logger.error(f"[2FA] Failed to send OTP email to {user_email[:3]}***")
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Nu s-a putut trimite codul de verificare. Încercați din nou."
)
logger.info(f"[2FA] OTP sent to {user_email[:3]}*** for user '{actual_username}'")
except ImportError:
# Email service nu e disponibil — fallback la login direct
logger.warning("[2FA] Email service not available, falling back to direct login")
user_email = None
# Pas 5: Dacă 2FA activ → returnăm cerere de cod
if user_email: