From e2d63d609a3dca1536b3298ec12095e03366eb47 Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Tue, 18 Nov 2025 10:45:16 +0200 Subject: [PATCH] Remove deprecated Telegram email auth plan document MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove TELEGRAM_EMAIL_AUTH_PLAN.md as email authentication feature was not implemented. The current authentication method via web app linking code remains the only supported method. ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- TELEGRAM_EMAIL_AUTH_PLAN.md | 1673 ----------------------------------- 1 file changed, 1673 deletions(-) delete mode 100644 TELEGRAM_EMAIL_AUTH_PLAN.md diff --git a/TELEGRAM_EMAIL_AUTH_PLAN.md b/TELEGRAM_EMAIL_AUTH_PLAN.md deleted file mode 100644 index 388c2df..0000000 --- a/TELEGRAM_EMAIL_AUTH_PLAN.md +++ /dev/null @@ -1,1673 +0,0 @@ -# Plan: Autentificare Telegram Bot prin Email + Parolฤƒ (2FA) - -**Data**: 2025-11-07 -**Autor**: Claude Code -**Status**: Planificat - Neรฎmplementat - ---- - -## ๐ŸŽฏ Obiectiv - -Implementare autentificare alternativฤƒ **email + parolฤƒ** pentru Telegram Bot, รฎn **paralel** cu metoda actualฤƒ (cod din web app). Ambele metode vor fi disponibile pentru toศ›i utilizatorii. - -**Cerinศ›e cheie:** -- โœ… Minimal invaziv - nu modifica logica existentฤƒ -- โœ… Ambele metode de autentificare รฎn paralel -- โœ…2FA real: email possession + parolฤƒ Oracle -- โœ… Simplu de testat cu un singur utilizator (mmarius28@gmail.com) - ---- - -## ๐Ÿ“Š Context: Sistemul Actual - -### Metoda Actualฤƒ de Autentificare (rฤƒmรขne neschimbatฤƒ) - -``` -1. User se autentificฤƒ รฎn web app (username + parolฤƒ) -2. User cere linking Telegram โ†’ backend genereazฤƒ cod 8-char -3. Backend salveazฤƒ cod รฎn telegram-bot via POST /internal/save-code -4. User trimite /start ABC123XY รฎn Telegram -5. Bot valideazฤƒ codul ศ™i auto-linkeazฤƒ (fฤƒrฤƒ parolฤƒ din nou) -6. User autentificat รฎn bot -``` - -**Caracteristici:** -- Nu necesitฤƒ email -- Necesitฤƒ acces la web app -- Auto-linking fฤƒrฤƒ re-introducere parolฤƒ -- Cod expirฤƒ รฎn 15 minute - ---- - -## ๐Ÿ”„ Noul Flux de Autentificare (Email + Parolฤƒ) - -### Flow Complet - -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 1. User: /login SAU apasฤƒ buton "๐Ÿ” Login cu Email" โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 2. Bot: "๐Ÿ“ง Introdu adresa ta de email Oracle:" โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 3. User: mmarius28@gmail.com โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 4. Bot: โ”‚ -โ”‚ - Verificฤƒ email รฎn Oracle UTILIZATORI table โ”‚ -โ”‚ - Genereazฤƒ cod 6-digit random โ”‚ -โ”‚ - Salveazฤƒ รฎn email_auth_codes (expiry 5 min) โ”‚ -โ”‚ - Trimite email SMTP: "Codul tฤƒu: 123456" โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 5. Bot: "โœ‰๏ธ Cod trimis pe email. Introdu codul (5 min):" โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 6. User: 123456 โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 7. Bot: โ”‚ -โ”‚ - Valideazฤƒ cod รฎn email_auth_codes โ”‚ -โ”‚ - Verificฤƒ expiry (5 minute) โ”‚ -โ”‚ - Marcheazฤƒ cod ca "used" โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 8. Bot: "๐Ÿ” Introdu parola ta Oracle:" โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 9. User: parola_mea (mesaj va fi ศ™ters automat) โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 10. Bot โ†’ Backend: โ”‚ -โ”‚ POST /api/telegram/auth/login-with-email โ”‚ -โ”‚ { โ”‚ -โ”‚ "email": "mmarius28@gmail.com", โ”‚ -โ”‚ "password": "parola_mea", โ”‚ -โ”‚ "telegram_user_id": 123456789 โ”‚ -โ”‚ } โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 11. Backend: โ”‚ -โ”‚ - Gฤƒseศ™te username din email รฎn UTILIZATORI โ”‚ -โ”‚ - Verificฤƒ parolฤƒ: pack_drepturi.verificautilizator() โ”‚ -โ”‚ - Genereazฤƒ JWT tokens (access + refresh) โ”‚ -โ”‚ - Returneazฤƒ tokens + user data โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 12. Bot: โ”‚ -โ”‚ - Salveazฤƒ JWT รฎn telegram_users table โ”‚ -โ”‚ - Linkeazฤƒ telegram_user_id cu oracle_username โ”‚ -โ”‚ - ศ˜terge mesajele cu parolฤƒ โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ†“ -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ 13. Bot: "โœ… Autentificat cu succes! Foloseศ™te /help" โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` - -### Conversation States (ConversationHandler) - -```python -AWAITING_EMAIL = 1 # Aศ™teaptฤƒ email de la user -AWAITING_CODE = 2 # Aศ™teaptฤƒ cod din email -AWAITING_PASSWORD = 3 # Aศ™teaptฤƒ parolฤƒ Oracle -``` - ---- - -## ๐Ÿ“ฆ Componente Noi (Arhitecturฤƒ) - -### 1. Email Service (SMTP Client) - -**Fiศ™ier NOU**: `reports-app/telegram-bot/app/utils/email_service.py` - -```python -import smtplib -from email.mime.text import MIMEText -from email.mime.multipart import MIMEMultipart -import os - -class EmailService: - def __init__(self): - self.smtp_host = os.getenv("SMTP_HOST", "mail.romfast.ro") - self.smtp_port = int(os.getenv("SMTP_PORT", "587")) - self.smtp_user = os.getenv("SMTP_USER", "ups@romfast.ro") - self.smtp_password = os.getenv("SMTP_PASSWORD", "#Ups2020#") - self.from_email = os.getenv("SMTP_FROM_EMAIL", "ups@romfast.ro") - self.from_name = os.getenv("SMTP_FROM_NAME", "ROA2WEB") - - async def send_auth_code(self, to_email: str, code: str, username: str) -> bool: - """ - Trimite cod de autentificare pe email - Returns: True dacฤƒ email trimis cu succes - """ - subject = "Codul tฤƒu de autentificare ROA2WEB" - - html_body = f""" - - -

๐Ÿ” Autentificare Telegram Bot

-

Salut {username},

-

Codul tฤƒu de autentificare este:

-

- {code} -

-

Codul expirฤƒ รฎn 5 minute.

-

Dacฤƒ nu ai solicitat acest cod, te rugฤƒm sฤƒ ignori acest email.

-
-

- ROA2WEB - ERP Reports Application -

- - - """ - - # Implementare SMTP cu error handling -``` - -**Funcศ›ii:** -- `send_auth_code(email, code, username)` - trimite cod pe email -- `_send_email(to, subject, html_body)` - helper SMTP generic -- Error handling cu retry logic (3 รฎncercฤƒri) - ---- - -### 2. Tabela SQLite Nouฤƒ: `email_auth_codes` - -**Locaศ›ie**: `reports-app/telegram-bot/app/db/database.py` - -**Schema SQL:** -```sql -CREATE TABLE IF NOT EXISTS email_auth_codes ( - code TEXT PRIMARY KEY, -- 6-digit numeric code (e.g., "123456") - email TEXT NOT NULL, -- Email utilizator din Oracle - oracle_username TEXT NOT NULL, -- Username Oracle asociat - telegram_user_id INTEGER NOT NULL, -- Telegram user ID care a solicitat - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - expires_at TIMESTAMP NOT NULL, -- Current time + 5 minute - used BOOLEAN DEFAULT 0, -- 0 = nefolosit, 1 = folosit - used_at TIMESTAMP, -- Timestamp cรขnd a fost folosit - - -- Index pentru query performance - INDEX idx_email (email), - INDEX idx_expires_at (expires_at), - INDEX idx_telegram_user_id (telegram_user_id) -); -``` - -**Operaศ›ii CRUD** (รฎn `app/db/operations.py`): -```python -async def create_email_auth_code(code: str, email: str, username: str, telegram_user_id: int) -> bool -async def get_email_auth_code(code: str) -> Optional[Dict] -async def mark_email_code_used(code: str) -> bool -async def delete_expired_email_codes() -> int -async def get_pending_email_code_for_user(telegram_user_id: int) -> Optional[Dict] -``` - -**Caracteristici:** -- Cod 6-digit random numeric (000000 - 999999) -- Expirare 5 minute -- One-time use (marcat ca `used=1`) -- Auto-cleanup de cฤƒtre job-ul existent (hourly) - ---- - -### 3. Backend Endpoint NOU: `POST /api/telegram/auth/login-with-email` - -**Locaศ›ie**: `reports-app/backend/app/routers/telegram.py` - -**Request Schema:** -```python -class TelegramEmailLoginRequest(BaseModel): - email: EmailStr - password: str - telegram_user_id: int - -class TelegramEmailLoginResponse(BaseModel): - success: bool - access_token: str - refresh_token: str - token_type: str = "bearer" - user_id: int - username: str - companies: List[CompanyInfo] - message: str -``` - -**Endpoint Logic:** -```python -@router.post("/auth/login-with-email", response_model=TelegramEmailLoginResponse) -async def login_with_email(request: TelegramEmailLoginRequest): - """ - Autentificare Telegram prin email + parolฤƒ - - Flow: - 1. Cautฤƒ username รฎn Oracle UTILIZATORI by email - 2. Verificฤƒ parolฤƒ prin pack_drepturi.verificautilizator(username, password) - 3. Dacฤƒ valid: genereazฤƒ JWT tokens - 4. Returneazฤƒ tokens + user data - """ - - async with oracle_pool.get_connection() as connection: - # 1. Find username by email - cursor = connection.cursor() - cursor.execute(""" - SELECT ID_UTIL, UTILIZATOR - FROM CONTAFIN_ORACLE.UTILIZATORI - WHERE UPPER(EMAIL) = UPPER(:email) - """, {"email": request.email}) - - user_row = cursor.fetchone() - if not user_row: - raise HTTPException(status_code=404, detail="Email not found") - - user_id, username = user_row - - # 2. Verify password via stored procedure - cursor.execute(""" - SELECT pack_drepturi.verificautilizator(:username, :password) - FROM DUAL - """, {"username": username, "password": request.password}) - - result = cursor.fetchone()[0] - if result == -1: - raise HTTPException(status_code=401, detail="Invalid password") - - # 3. Get user companies - companies = get_user_companies(user_id, connection) - - # 4. Generate JWT tokens - access_token = create_access_token(...) - refresh_token = create_refresh_token(...) - - return TelegramEmailLoginResponse( - success=True, - access_token=access_token, - refresh_token=refresh_token, - user_id=user_id, - username=username, - companies=companies, - message="Authentication successful" - ) -``` - -**Securitate:** -- Rate limiting: 5 requests / 5 minutes per telegram_user_id -- Password validation prin Oracle stored procedure (nu stocฤƒm parole) -- HTTPS required รฎn producศ›ie -- Logging pentru failed attempts - ---- - -### 4. Bot Handlers NOI: `/login` + ConversationHandler - -**Fiศ™ier NOU**: `reports-app/telegram-bot/app/bot/email_handlers.py` - -#### Command: `/login` - -```python -from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup -from telegram.ext import ContextTypes, ConversationHandler, CommandHandler, MessageHandler, filters - -# Conversation states -AWAITING_EMAIL, AWAITING_CODE, AWAITING_PASSWORD = range(3) - -async def login_command(update: Update, context: ContextTypes.DEFAULT_TYPE): - """ - Handler pentru /login command - Iniศ›iazฤƒ conversation pentru email auth - """ - user = update.effective_user - - # Check dacฤƒ e deja autentificat - if await is_user_authenticated(user.id): - await update.message.reply_text( - "โœ… Eศ™ti deja autentificat!\n" - "Foloseศ™te /unlink pentru a te deautentifica." - ) - return ConversationHandler.END - - # Afiศ™eazฤƒ metode de autentificare - keyboard = [ - [InlineKeyboardButton("๐Ÿ” Login cu Email", callback_data="email_login")], - [InlineKeyboardButton("๐ŸŒ Login din Web App", callback_data="web_login")], - [InlineKeyboardButton("โŒ Anuleazฤƒ", callback_data="cancel")] - ] - reply_markup = InlineKeyboardMarkup(keyboard) - - await update.message.reply_text( - "๐Ÿ”‘ Alege metoda de autentificare:\n\n" - "๐Ÿ“ง **Email + Parolฤƒ**: Primeศ™ti cod pe email, apoi introduci parola\n" - "๐ŸŒ **Web App**: Genereazฤƒ cod din aplicaศ›ia web", - reply_markup=reply_markup - ) - - return AWAITING_EMAIL - -async def email_login_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): - """Callback pentru butonul 'Login cu Email'""" - query = update.callback_query - await query.answer() - - await query.edit_message_text( - "๐Ÿ“ง **Autentificare prin Email**\n\n" - "Te rugฤƒm sฤƒ introduci adresa ta de email Oracle:\n" - "(Exemplu: nume.prenume@companie.ro)" - ) - - return AWAITING_EMAIL - -async def receive_email(update: Update, context: ContextTypes.DEFAULT_TYPE): - """ - Handler pentru primirea email-ului - """ - email = update.message.text.strip() - user_id = update.effective_user.id - - # Validare format email - if not is_valid_email(email): - await update.message.reply_text( - "โŒ Email invalid. Te rugฤƒm sฤƒ introduci o adresฤƒ de email validฤƒ." - ) - return AWAITING_EMAIL - - # Verificฤƒ email รฎn Oracle + trimite cod - try: - # 1. Verificฤƒ email รฎn Oracle UTILIZATORI - username = await verify_email_in_oracle(email) - if not username: - await update.message.reply_text( - "โŒ Email-ul nu este รฎnregistrat รฎn sistem.\n" - "Contacteazฤƒ administratorul pentru a-ศ›i adฤƒuga email-ul." - ) - return ConversationHandler.END - - # 2. Genereazฤƒ cod 6-digit - code = generate_6digit_code() - - # 3. Salveazฤƒ รฎn email_auth_codes - await save_email_auth_code( - code=code, - email=email, - username=username, - telegram_user_id=user_id - ) - - # 4. Trimite email - email_sent = await email_service.send_auth_code(email, code, username) - - if not email_sent: - await update.message.reply_text( - "โŒ Eroare la trimiterea email-ului. Te rugฤƒm sฤƒ รฎncerci din nou." - ) - return ConversationHandler.END - - # 5. Salveazฤƒ email รฎn context - context.user_data['pending_email'] = email - context.user_data['pending_username'] = username - - await update.message.reply_text( - f"โœ‰๏ธ **Cod trimis pe {email}**\n\n" - "Verificฤƒ inbox-ul (ศ™i spam) ศ™i introdu codul de 6 cifre.\n" - "โฑ Codul expirฤƒ รฎn **5 minute**.\n\n" - "Scrie /cancel pentru a anula." - ) - - return AWAITING_CODE - - except Exception as e: - logger.error(f"Email login error: {e}") - await update.message.reply_text( - "โŒ Eroare internฤƒ. Te rugฤƒm sฤƒ รฎncerci din nou mai tรขrziu." - ) - return ConversationHandler.END - -async def receive_code(update: Update, context: ContextTypes.DEFAULT_TYPE): - """ - Handler pentru primirea codului din email - """ - code = update.message.text.strip() - user_id = update.effective_user.id - - # Validare format cod (6 digits) - if not code.isdigit() or len(code) != 6: - await update.message.reply_text( - "โŒ Cod invalid. Introdu cele 6 cifre din email." - ) - return AWAITING_CODE - - # Verificฤƒ cod รฎn DB - try: - code_data = await get_email_auth_code(code) - - if not code_data: - await update.message.reply_text( - "โŒ Cod invalid sau expirat. Te rugฤƒm sฤƒ reรฎncepi cu /login" - ) - return ConversationHandler.END - - # Verificฤƒri - if code_data['used']: - await update.message.reply_text( - "โŒ Cod deja folosit. Te rugฤƒm sฤƒ reรฎncepi cu /login" - ) - return ConversationHandler.END - - if code_data['telegram_user_id'] != user_id: - await update.message.reply_text( - "โŒ Codul nu รฎศ›i aparศ›ine." - ) - return ConversationHandler.END - - if datetime.now() > code_data['expires_at']: - await update.message.reply_text( - "โŒ Codul a expirat. Te rugฤƒm sฤƒ reรฎncepi cu /login" - ) - return ConversationHandler.END - - # Marcheazฤƒ cod ca folosit - await mark_email_code_used(code) - - # Salveazฤƒ username รฎn context - context.user_data['verified_username'] = code_data['oracle_username'] - context.user_data['verified_email'] = code_data['email'] - - await update.message.reply_text( - "โœ… **Cod validat cu succes!**\n\n" - "๐Ÿ” Acum introdu parola ta Oracle:\n" - "(Parola va fi ศ™tearsฤƒ automat dupฤƒ verificare)" - ) - - return AWAITING_PASSWORD - - except Exception as e: - logger.error(f"Code validation error: {e}") - await update.message.reply_text( - "โŒ Eroare la validarea codului. Te rugฤƒm sฤƒ รฎncerci din nou." - ) - return ConversationHandler.END - -async def receive_password(update: Update, context: ContextTypes.DEFAULT_TYPE): - """ - Handler pentru primirea parolei - """ - password = update.message.text.strip() - user_id = update.effective_user.id - - # ศ˜terge imediat mesajul cu parola - try: - await update.message.delete() - except: - pass - - username = context.user_data.get('verified_username') - email = context.user_data.get('verified_email') - - if not username or not email: - await update.effective_chat.send_message( - "โŒ Sesiune expiratฤƒ. Te rugฤƒm sฤƒ reรฎncepi cu /login" - ) - return ConversationHandler.END - - # Trimite loading message - loading_msg = await update.effective_chat.send_message( - "โณ Verificare credenศ›iale..." - ) - - try: - # Call backend endpoint - response = await backend_client.login_with_email( - email=email, - password=password, - telegram_user_id=user_id - ) - - if not response['success']: - await loading_msg.edit_text( - "โŒ Parolฤƒ incorectฤƒ. Te rugฤƒm sฤƒ reรฎncepi cu /login" - ) - return ConversationHandler.END - - # Salveazฤƒ user รฎn telegram_users - await save_telegram_user( - telegram_user_id=user_id, - username=update.effective_user.username, - first_name=update.effective_user.first_name, - last_name=update.effective_user.last_name, - oracle_username=response['username'], - jwt_token=response['access_token'], - jwt_refresh_token=response['refresh_token'] - ) - - # Success message - companies_list = "\n".join([f"โ€ข {c['name']}" for c in response['companies'][:5]]) - - await loading_msg.edit_text( - f"โœ… **Autentificat cu succes!**\n\n" - f"๐Ÿ‘ค Utilizator: **{response['username']}**\n" - f"๐Ÿข Companii disponibile: {len(response['companies'])}\n\n" - f"{companies_list}\n\n" - f"Foloseศ™te /help pentru comenzi disponibile." - ) - - # Clear context - context.user_data.clear() - - return ConversationHandler.END - - except Exception as e: - logger.error(f"Password verification error: {e}") - await loading_msg.edit_text( - "โŒ Eroare la autentificare. Te rugฤƒm sฤƒ รฎncerci din nou cu /login" - ) - return ConversationHandler.END - -async def cancel_login(update: Update, context: ContextTypes.DEFAULT_TYPE): - """Cancel conversation""" - context.user_data.clear() - await update.message.reply_text("โŒ Autentificare anulatฤƒ.") - return ConversationHandler.END - -# ConversationHandler setup -email_login_handler = ConversationHandler( - entry_points=[ - CommandHandler('login', login_command), - CallbackQueryHandler(email_login_callback, pattern='^email_login$') - ], - states={ - AWAITING_EMAIL: [MessageHandler(filters.TEXT & ~filters.COMMAND, receive_email)], - AWAITING_CODE: [MessageHandler(filters.TEXT & ~filters.COMMAND, receive_code)], - AWAITING_PASSWORD: [MessageHandler(filters.TEXT & ~filters.COMMAND, receive_password)], - }, - fallbacks=[ - CommandHandler('cancel', cancel_login), - CallbackQueryHandler(cancel_login, pattern='^cancel$') - ], - conversation_timeout=300 # 5 minute timeout -) -``` - -**Handler Registration** (รฎn `app/bot/handlers.py`): -```python -from app.bot.email_handlers import email_login_handler - -def setup_handlers(application): - # ... existing handlers ... - - # Email login handler - application.add_handler(email_login_handler) -``` - ---- - -### 5. Backend API Client Method - -**Locaศ›ie**: `reports-app/telegram-bot/app/api/client.py` - -```python -class BackendAPIClient: - # ... existing methods ... - - async def login_with_email( - self, - email: str, - password: str, - telegram_user_id: int - ) -> dict: - """ - Login via email + password - """ - try: - response = await self.client.post( - f"{self.base_url}/api/telegram/auth/login-with-email", - json={ - "email": email, - "password": password, - "telegram_user_id": telegram_user_id - } - ) - response.raise_for_status() - return response.json() - except httpx.HTTPError as e: - logger.error(f"Email login failed: {e}") - raise -``` - ---- - -## ๐Ÿ”ง Environment Variables - -### Backend `.env` (nu necesitฤƒ modificฤƒri - doar pentru referinศ›ฤƒ) -```bash -# Existente (nu modificฤƒm) -ORACLE_USER=CONTAFIN_ORACLE -ORACLE_PASSWORD=your_password -ORACLE_HOST=localhost -ORACLE_PORT=1526 -ORACLE_SID=ROA -JWT_SECRET_KEY=your_secret_key -JWT_ALGORITHM=HS256 -JWT_EXPIRE_MINUTES=30 -``` - -### Telegram Bot `.env` (ADAUGฤ‚ ACESTEA) -```bash -# Existing -TELEGRAM_BOT_TOKEN=your_bot_token -BACKEND_URL=http://localhost:8000 -DATABASE_PATH=data/telegram_bot.db - -# NEW: SMTP Configuration -SMTP_HOST=mail.romfast.ro -SMTP_PORT=587 -SMTP_USER=ups@romfast.ro -SMTP_PASSWORD=#Ups2020# -SMTP_FROM_EMAIL=ups@romfast.ro -SMTP_FROM_NAME=ROA2WEB -SMTP_USE_TLS=true - -# NEW: Email Auth Settings -EMAIL_CODE_EXPIRY_MINUTES=5 -EMAIL_CODE_LENGTH=6 -MAX_EMAIL_ATTEMPTS_PER_HOUR=3 -``` - ---- - -## ๐Ÿ”’ Securitate & Validฤƒri - -### 1. Email Validation -```python -import re - -def is_valid_email(email: str) -> bool: - """Validare format email""" - pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' - return bool(re.match(pattern, email)) - -async def verify_email_in_oracle(email: str) -> Optional[str]: - """ - Verificฤƒ dacฤƒ email existฤƒ รฎn Oracle UTILIZATORI - Returns: username dacฤƒ existฤƒ, None altfel - """ - async with oracle_pool.get_connection() as connection: - cursor = connection.cursor() - cursor.execute(""" - SELECT UTILIZATOR - FROM CONTAFIN_ORACLE.UTILIZATORI - WHERE UPPER(EMAIL) = UPPER(:email) - AND ACTIV = 1 - """, {"email": email}) - - row = cursor.fetchone() - return row[0] if row else None -``` - -### 2. Code Generation & Storage -```python -import random -import string -from datetime import datetime, timedelta - -def generate_6digit_code() -> str: - """Genereazฤƒ cod random 6-digit""" - return ''.join(random.choices(string.digits, k=6)) - -async def save_email_auth_code( - code: str, - email: str, - username: str, - telegram_user_id: int -) -> bool: - """Salveazฤƒ cod รฎn DB cu expiry 5 minute""" - expires_at = datetime.now() + timedelta(minutes=5) - - async with get_db_connection() as db: - await db.execute(""" - INSERT INTO email_auth_codes - (code, email, oracle_username, telegram_user_id, expires_at) - VALUES (?, ?, ?, ?, ?) - """, (code, email, username, telegram_user_id, expires_at)) - await db.commit() - - return True -``` - -### 3. Rate Limiting -```python -from collections import defaultdict -from datetime import datetime, timedelta - -# In-memory rate limiter (sau Redis รฎn producศ›ie) -email_attempts = defaultdict(list) - -async def check_rate_limit(identifier: str, max_attempts: int = 3, window_minutes: int = 60) -> bool: - """ - Rate limiting pentru email requests - identifier poate fi: email sau telegram_user_id - """ - now = datetime.now() - cutoff = now - timedelta(minutes=window_minutes) - - # Curฤƒศ›ฤƒ attempts vechi - email_attempts[identifier] = [ - attempt for attempt in email_attempts[identifier] - if attempt > cutoff - ] - - # Verificฤƒ limita - if len(email_attempts[identifier]) >= max_attempts: - return False # Rate limit exceeded - - # Adaugฤƒ attempt nou - email_attempts[identifier].append(now) - return True # OK to proceed -``` - -### 4. Password Security -```python -async def receive_password(update: Update, context: ContextTypes.DEFAULT_TYPE): - """Handler cu securitate mฤƒrite pentru parolฤƒ""" - password = update.message.text.strip() - - # 1. ศ˜terge IMEDIAT mesajul cu parola - try: - await update.message.delete() - except Exception as e: - logger.warning(f"Could not delete password message: {e}") - - # 2. NU loga parola niciodatฤƒ - logger.info(f"Password received for user {update.effective_user.id}") - - # 3. Verificฤƒ parola prin backend (Oracle) - # ... (vezi cod de mai sus) - - # 4. ศ˜terge parola din memorie - del password -``` - -### 5. Auto-Cleanup Job -```python -async def cleanup_expired_codes(): - """Job periodic pentru curฤƒศ›area codurilor expirate""" - while True: - try: - async with get_db_connection() as db: - # ศ˜terge email codes expirate - await db.execute(""" - DELETE FROM email_auth_codes - WHERE expires_at < ? - OR (used = 1 AND used_at < ?) - """, ( - datetime.now(), - datetime.now() - timedelta(days=1) # Cleanup used codes dupฤƒ 1 zi - )) - await db.commit() - - deleted = db.total_changes - logger.info(f"Cleaned up {deleted} expired email auth codes") - - except Exception as e: - logger.error(f"Cleanup job error: {e}") - - # Run every hour - await asyncio.sleep(3600) - -# Start cleanup job รฎn main.py -asyncio.create_task(cleanup_expired_codes()) -``` - ---- - -## ๐Ÿ“ Fiศ™iere Modificate/Create - -### **CREATE** (6 fiศ™iere noi): - -1. **`reports-app/telegram-bot/app/utils/email_service.py`** - - SMTP client pentru trimitere email-uri - - Funcศ›ie: `send_auth_code(email, code, username)` - - Error handling + retry logic - -2. **`reports-app/telegram-bot/app/auth/email_auth.py`** - - Logicฤƒ autentificare email - - Funcศ›ii: `verify_email_in_oracle()`, `generate_6digit_code()`, `check_rate_limit()` - -3. **`reports-app/telegram-bot/app/bot/email_handlers.py`** - - ConversationHandler pentru `/login` - - States: AWAITING_EMAIL โ†’ AWAITING_CODE โ†’ AWAITING_PASSWORD - - Handlers: `receive_email()`, `receive_code()`, `receive_password()` - -4. **`reports-app/backend/app/schemas/telegram_email_auth.py`** - - Pydantic schemas pentru email auth - - `TelegramEmailLoginRequest`, `TelegramEmailLoginResponse` - -5. **`reports-app/telegram-bot/tests/test_email_auth.py`** - - Unit tests pentru email auth flow - - Mock SMTP, Oracle, backend API - -6. **`TELEGRAM_EMAIL_AUTH_PLAN.md`** - - Acest document (plan detaliat) - -### **MODIFY** (6 fiศ™iere existente): - -1. **`reports-app/telegram-bot/app/db/database.py`** - - **Adaugฤƒ**: Schema tabela `email_auth_codes` - - **Linie**: ~40-60 (รฎn funcศ›ia `init_database()`) - -2. **`reports-app/telegram-bot/app/db/operations.py`** - - **Adaugฤƒ**: CRUD operations pentru `email_auth_codes` - - Funcศ›ii noi: `create_email_auth_code()`, `get_email_auth_code()`, `mark_email_code_used()`, etc. - - **Linii**: ~200-300 (la final de fiศ™ier) - -3. **`reports-app/telegram-bot/app/bot/handlers.py`** - - **Adaugฤƒ**: Import ศ™i register `email_login_handler` - - **Linie**: ~10 (import), ~150 (register รฎn `setup_handlers()`) - - **Modificare**: Update `/start` message pentru a menศ›iona `/login` - -4. **`reports-app/backend/app/routers/telegram.py`** - - **Adaugฤƒ**: Endpoint `POST /auth/login-with-email` - - **Linii**: ~200-300 (la final de fiศ™ier) - - **Import**: Adaugฤƒ schema `TelegramEmailLoginRequest/Response` - -5. **`reports-app/telegram-bot/app/api/client.py`** - - **Adaugฤƒ**: Method `login_with_email(email, password, telegram_user_id)` - - **Linii**: ~150-180 (รฎn clasa `BackendAPIClient`) - -6. **`reports-app/telegram-bot/.env`** - - **Adaugฤƒ**: SMTP configuration variables (vezi secศ›iunea Environment Variables) - -### **NO TOUCH** (rฤƒmรขn 100% neschimbate): - -- โœ… Fluxul actual de linking (web app โ†’ cod โ†’ /start) -- โœ… Tabele existente: `telegram_users`, `telegram_auth_codes`, `telegram_sessions` -- โœ… Endpoint-uri existente: `/generate-code`, `/verify-user`, `/refresh-token` -- โœ… Handler-e existente: `/start [code]`, `/companies`, `/dashboard`, `/facturi`, etc. -- โœ… Toate comenzile Telegram existente (funcศ›ionalitate pฤƒstratฤƒ 100%) - ---- - -## ๐Ÿงช Testing Strategy - -### 1. Unit Tests - -**Fiศ™ier**: `reports-app/telegram-bot/tests/test_email_auth.py` - -```python -import pytest -from unittest.mock import AsyncMock, patch -from app.auth.email_auth import verify_email_in_oracle, generate_6digit_code, check_rate_limit -from app.utils.email_service import EmailService - -@pytest.mark.asyncio -async def test_generate_6digit_code(): - """Test generare cod 6-digit""" - code = generate_6digit_code() - assert len(code) == 6 - assert code.isdigit() - -@pytest.mark.asyncio -async def test_verify_email_in_oracle_success(): - """Test verificare email valid รฎn Oracle""" - with patch('app.auth.email_auth.oracle_pool') as mock_pool: - # Mock Oracle response - mock_cursor = AsyncMock() - mock_cursor.fetchone.return_value = ("test_user",) - - username = await verify_email_in_oracle("test@example.com") - assert username == "test_user" - -@pytest.mark.asyncio -async def test_verify_email_not_found(): - """Test email inexistent รฎn Oracle""" - with patch('app.auth.email_auth.oracle_pool') as mock_pool: - mock_cursor = AsyncMock() - mock_cursor.fetchone.return_value = None - - username = await verify_email_in_oracle("notfound@example.com") - assert username is None - -@pytest.mark.asyncio -async def test_rate_limiting(): - """Test rate limiting pentru email requests""" - identifier = "test_user_123" - - # First 3 attempts should pass - for i in range(3): - result = await check_rate_limit(identifier, max_attempts=3, window_minutes=60) - assert result is True - - # 4th attempt should fail - result = await check_rate_limit(identifier, max_attempts=3, window_minutes=60) - assert result is False - -@pytest.mark.asyncio -async def test_email_service_send_code(): - """Test trimitere email cu cod""" - email_service = EmailService() - - with patch('app.utils.email_service.smtplib.SMTP') as mock_smtp: - result = await email_service.send_auth_code( - to_email="test@example.com", - code="123456", - username="test_user" - ) - - assert result is True - assert mock_smtp.called -``` - -### 2. Integration Tests - -```python -@pytest.mark.asyncio -async def test_full_email_auth_flow(): - """Test complet: email โ†’ cod โ†’ parolฤƒ โ†’ JWT""" - - # 1. Request email code - email = "mmarius28@gmail.com" - telegram_user_id = 123456789 - - with patch('app.auth.email_auth.verify_email_in_oracle') as mock_verify: - mock_verify.return_value = "marius_user" - - # Generate code - code = generate_6digit_code() - await save_email_auth_code(code, email, "marius_user", telegram_user_id) - - # 2. Validate code - code_data = await get_email_auth_code(code) - assert code_data is not None - assert code_data['email'] == email - assert code_data['used'] is False - - # 3. Mock backend login - with patch('app.api.client.BackendAPIClient.login_with_email') as mock_login: - mock_login.return_value = { - 'success': True, - 'access_token': 'test_jwt_token', - 'refresh_token': 'test_refresh_token', - 'username': 'marius_user', - 'user_id': 42, - 'companies': [] - } - - # Verify password - response = await backend_client.login_with_email( - email=email, - password="test_password", - telegram_user_id=telegram_user_id - ) - - assert response['success'] is True - assert 'access_token' in response -``` - -### 3. Manual Testing Checklist - -**Fiศ™ier**: `reports-app/telegram-bot/tests/MANUAL_EMAIL_AUTH_TESTING.md` - -```markdown -# Manual Testing Checklist - Email Authentication - -## Prerequisites -- [ ] Backend running on port 8000 -- [ ] Telegram bot running -- [ ] SMTP credentials configured in .env -- [ ] Test email: mmarius28@gmail.com exists in Oracle UTILIZATORI table - -## Test Cases - -### 1. Successful Authentication Flow -- [ ] Start bot: `/start` -- [ ] Type: `/login` -- [ ] Select "๐Ÿ” Login cu Email" -- [ ] Enter email: `mmarius28@gmail.com` -- [ ] Verify email received with 6-digit code -- [ ] Enter code from email -- [ ] Enter Oracle password -- [ ] Verify success message with companies list -- [ ] Test command: `/companies` (should work) - -### 2. Invalid Email -- [ ] `/login` -- [ ] Enter email: `nonexistent@example.com` -- [ ] Verify error message: "Email-ul nu este รฎnregistrat" - -### 3. Expired Code -- [ ] `/login` โ†’ enter valid email -- [ ] Wait 6 minutes (code expiry = 5 min) -- [ ] Enter code -- [ ] Verify error: "Cod expirat" - -### 4. Wrong Code -- [ ] `/login` โ†’ enter valid email -- [ ] Enter wrong code: `999999` -- [ ] Verify error: "Cod invalid" - -### 5. Wrong Password -- [ ] `/login` โ†’ enter email โ†’ enter valid code -- [ ] Enter wrong password -- [ ] Verify error: "Parolฤƒ incorectฤƒ" - -### 6. Rate Limiting -- [ ] `/login` โ†’ enter email (attempt 1) -- [ ] `/cancel` -- [ ] `/login` โ†’ enter email (attempt 2) -- [ ] `/cancel` -- [ ] `/login` โ†’ enter email (attempt 3) -- [ ] `/cancel` -- [ ] `/login` โ†’ enter email (attempt 4) -- [ ] Verify error: "Prea multe รฎncercฤƒri. รŽncearcฤƒ รฎn 60 minute" - -### 7. Password Message Deletion -- [ ] `/login` โ†’ enter email โ†’ enter code -- [ ] Enter password -- [ ] Verify password message is deleted immediately -- [ ] Check chat history - password should not be visible - -### 8. Cancel Flow -- [ ] `/login` -- [ ] `/cancel` (should cancel and clear state) - -### 9. Already Authenticated -- [ ] Complete successful login -- [ ] Type `/login` again -- [ ] Verify message: "Eศ™ti deja autentificat" - -### 10. Parallel Method (Web App Linking) Still Works -- [ ] Login to web app: http://localhost:3000 -- [ ] Generate Telegram linking code -- [ ] Use `/start ABC123XY` in Telegram -- [ ] Verify linking works as before (OLD method) - -### 11. Database Cleanup -- [ ] Create expired codes (manually set expires_at in past) -- [ ] Wait for hourly cleanup job -- [ ] Verify expired codes deleted from `email_auth_codes` table -``` - ---- - -## ๐Ÿ“Š Estimare Efort & Timeline - -### Breakdown Detaliat - -| Componentฤƒ | Efort (ore) | Detalii | -|-----------|-------------|---------| -| **Backend** | | | -| โ†’ Endpoint `/login-with-email` | 1.5h | Logic + Oracle queries + JWT | -| โ†’ Schema Pydantic | 0.5h | Request/Response models | -| โ†’ Rate limiting | 0.5h | Middleware sau decorator | -| โ†’ Testing backend | 0.5h | Unit tests endpoint | -| **Telegram Bot** | | | -| โ†’ Email service (SMTP) | 1.5h | Client SMTP + templates + retry | -| โ†’ DB schema + operations | 1h | Tabela nouฤƒ + CRUD | -| โ†’ Email auth logic | 1h | Verificare email, cod generation | -| โ†’ ConversationHandler | 2h | States + handlers + callbacks | -| โ†’ API client method | 0.5h | Method nou รฎn BackendAPIClient | -| โ†’ Testing bot | 1h | Unit + integration tests | -| **Integration** | | | -| โ†’ End-to-end testing | 1h | Flow complet manual | -| โ†’ Bug fixes | 1h | Edge cases | -| **Documentation** | | | -| โ†’ Update README | 0.5h | Secศ›iune nouฤƒ pentru email auth | -| โ†’ Update TELEGRAM_COMMANDS.md | 0.5h | Documentare `/login` | -| **TOTAL** | **~13h** | ~2 zile lucru (6-7h/zi) | - -### Timeline Recomandat - -**Ziua 1 (6-7h):** -1. Setup environment (SMTP config) - 0.5h -2. Backend: Endpoint + schema - 2h -3. Telegram Bot: Email service - 1.5h -4. Telegram Bot: DB schema + operations - 1h -5. Testing preliminar - 1h - -**Ziua 2 (6-7h):** -1. Telegram Bot: ConversationHandler - 2h -2. Email auth logic - 1h -3. Integration - 1h -4. End-to-end testing - 1.5h -5. Documentation - 0.5h -6. Bug fixes - 1h - ---- - -## โœ… Avantaje Plan - -| Avantaj | Detalii | -|---------|---------| -| โœ… **Minimal Invaziv** | 0 modificฤƒri la logica existentฤƒ, doar adฤƒugiri | -| โœ… **Ambele Metode** | Users pot alege: email+parolฤƒ SAU web app linking | -| โœ… **Backward Compatible** | Utilizatori fฤƒrฤƒ email folosesc metoda actualฤƒ | -| โœ… **2FA Real** | Email possession (cod) + parolฤƒ Oracle = 2 factori | -| โœ… **Simplu de Testat** | Un singur utilizator cu email (mmarius28@gmail.com) | -| โœ… **Extensibil** | Uศ™or de activat pentru alศ›i useri cรขnd adaugi email-uri | -| โœ… **Securitate Mฤƒrite** | Rate limiting, code expiry, password verification รฎn Oracle | -| โœ… **Auto-Cleanup** | Job existent curฤƒศ›ฤƒ automat coduri expirate | -| โœ… **User-Friendly** | Conversation flow natural รฎn Telegram | -| โœ… **Error Handling** | Mesaje clare pentru fiecare caz de eroare | - ---- - -## ๐Ÿš€ Ordine Implementare (Step-by-Step) - -### **Step 1: Environment Setup** (15 min) - -1. Adaugฤƒ SMTP credentials รฎn `.env`: -```bash -cd reports-app/telegram-bot/ -echo "SMTP_HOST=mail.romfast.ro" >> .env -echo "SMTP_PORT=587" >> .env -echo "SMTP_USER=ups@romfast.ro" >> .env -echo "SMTP_PASSWORD=#Ups2020#" >> .env -echo "SMTP_FROM_EMAIL=ups@romfast.ro" >> .env -echo "SMTP_FROM_NAME=ROA2WEB" >> .env -``` - -2. Install dependencies: -```bash -pip install aiosmtplib # Async SMTP client -``` - -### **Step 2: Backend - Endpoint** (2h) - -1. Create schema: `backend/app/schemas/telegram_email_auth.py` -2. Add endpoint รฎn `backend/app/routers/telegram.py` -3. Test cu Postman/curl - -### **Step 3: Telegram Bot - Infrastructure** (2.5h) - -1. Create `app/utils/email_service.py` (SMTP client) -2. Update `app/db/database.py` (add `email_auth_codes` table) -3. Update `app/db/operations.py` (CRUD operations) -4. Test DB operations - -### **Step 4: Telegram Bot - Auth Logic** (1h) - -1. Create `app/auth/email_auth.py` -2. Implement: `verify_email_in_oracle()`, `generate_6digit_code()`, `check_rate_limit()` -3. Unit tests - -### **Step 5: Telegram Bot - Handlers** (2h) - -1. Create `app/bot/email_handlers.py` -2. Implement ConversationHandler -3. Register รฎn `app/bot/handlers.py` - -### **Step 6: Backend API Client** (30 min) - -1. Add `login_with_email()` method รฎn `app/api/client.py` - -### **Step 7: Integration Testing** (1h) - -1. Start backend + bot -2. Test flow complet cu mmarius28@gmail.com -3. Fix bugs - -### **Step 8: Comprehensive Testing** (1.5h) - -1. Run all test cases from checklist -2. Test edge cases -3. Verify both methods work in parallel - -### **Step 9: Documentation** (30 min) - -1. Update README.md -2. Update TELEGRAM_COMMANDS.md -3. Create MANUAL_EMAIL_AUTH_TESTING.md - ---- - -## ๐Ÿ› Troubleshooting Guide - -### Issue: Email nu ajunge - -**Cauze posibile:** -1. SMTP credentials incorecte -2. Port blocat (587) -3. Email รฎn spam - -**Debugging:** -```python -# Test SMTP connection -import smtplib - -try: - server = smtplib.SMTP('mail.romfast.ro', 587) - server.starttls() - server.login('ups@romfast.ro', '#Ups2020#') - print("โœ… SMTP connection OK") - server.quit() -except Exception as e: - print(f"โŒ SMTP error: {e}") -``` - -### Issue: Cod invalid/expirat - -**Debugging:** -```sql --- Check code in DB -SELECT * FROM email_auth_codes WHERE code = '123456'; - --- Check expiry -SELECT code, expires_at, - datetime('now') as now, - (julianday(expires_at) - julianday('now')) * 24 * 60 as minutes_remaining -FROM email_auth_codes -WHERE code = '123456'; -``` - -### Issue: Parolฤƒ incorectฤƒ (dar ศ™tiu cฤƒ e corectฤƒ) - -**Cauze posibile:** -1. Username gฤƒsit greศ™it din email -2. Oracle stored procedure error - -**Debugging:** -```python -# Test Oracle auth direct -async with oracle_pool.get_connection() as connection: - cursor = connection.cursor() - - # 1. Check email โ†’ username mapping - cursor.execute(""" - SELECT UTILIZATOR, EMAIL - FROM CONTAFIN_ORACLE.UTILIZATORI - WHERE UPPER(EMAIL) = UPPER('mmarius28@gmail.com') - """) - print(cursor.fetchone()) - - # 2. Test stored procedure - cursor.execute(""" - SELECT pack_drepturi.verificautilizator('marius_user', 'parola_mea') - FROM DUAL - """) - result = cursor.fetchone()[0] - print(f"Auth result: {result}") # -1 = fail, user_id = success -``` - -### Issue: Rate limiting prea restrictiv - -**Quick fix:** -```python -# รŽn email_auth.py, increase limits -MAX_EMAIL_ATTEMPTS = 5 # was 3 -RATE_LIMIT_WINDOW_MINUTES = 30 # was 60 -``` - ---- - -## ๐Ÿ“š Additional Documentation - -### Email Template (HTML) - -```html - - - - - - -
-
-

๐Ÿ” ROA2WEB

-

Autentificare Telegram Bot

-
- -
-

Salut {{username}},

- -

Ai solicitat autentificarea รฎn aplicaศ›ia ROA2WEB Telegram Bot.

- -
-

Codul tฤƒu de autentificare:

-

{{code}}

-
- -
- โฑ๏ธ Important: Acest cod expirฤƒ รฎn 5 minute. -
- -

Introdu acest cod รฎn conversaศ›ia cu Telegram Bot, apoi vei fi solicitat sฤƒ introduci parola.

- -

- Nu ai solicitat acest cod?
- Dacฤƒ nu ai iniศ›iat aceastฤƒ autentificare, te rugฤƒm sฤƒ ignori acest email. - Nimeni nu va avea acces la contul tฤƒu fฤƒrฤƒ parola ta. -

-
- - -
- - -``` - -### Command Reference Update - -Adaugฤƒ รฎn `TELEGRAM_COMMANDS.md`: - -```markdown -## /login - -**Descriere**: Autentificare รฎn Telegram Bot prin email + parolฤƒ (2FA) - -**Sintaxฤƒ**: `/login` - -**Flow**: -1. Selectezi metoda de autentificare (Email sau Web App) -2. Pentru Email: - - Introduci adresa de email Oracle - - Primeศ™ti cod pe email (6 cifre) - - Introduci codul din email - - Introduci parola Oracle - - Primeศ™ti confirmare ศ™i acces la comenzi - -**Exemple**: -``` -/login -โ†’ Selecteazฤƒ "๐Ÿ” Login cu Email" -โ†’ Introdu: mmarius28@gmail.com -โ†’ Verificฤƒ email ศ™i introdu cod: 123456 -โ†’ Introdu parola -โ†’ โœ… Autentificat cu succes! -``` - -**Securitate**: -- Cod expirฤƒ รฎn 5 minute -- Cod utilizabil o singurฤƒ datฤƒ -- Parolฤƒ verificatฤƒ รฎn Oracle -- Mesajul cu parola este ศ™ters automat -- Rate limiting: max 3 รฎncercฤƒri/orฤƒ - -**Comandฤƒ alternativฤƒ**: Buton "๐Ÿ” Login cu Email" รฎn meniu principal -``` - ---- - -## ๐ŸŽ“ Learning Points & Best Practices - -### 1. De ce 6-digit code รฎn loc de 8-char alphanumeric? - -**Rฤƒspuns**: -- Mai uศ™or de tastat pe mobile -- Mai puศ›in prone la erori (0/O, 1/I confusion) -- Suficient de securizat pentru 5 minute expiry -- Standard รฎn industrie (Google, GitHub, etc.) - -### 2. De ce 5 minute expiry pentru cod? - -**Rฤƒspuns**: -- Balans รฎntre security ศ™i UX -- Suficient timp pentru check email + type code -- Redus attack window pentru code guessing -- Similar cu alte aplicaศ›ii 2FA - -### 3. De ce ศ™terge mesajul cu parola? - -**Rฤƒspuns**: -- Securitate: parola nu rฤƒmรขne รฎn chat history -- Telegram API permite ศ™tergerea mesajelor -- Best practice รฎn bot-uri care cer credenศ›iale -- Protecศ›ie dacฤƒ telefonul e compromis - -### 4. De ce รฎn-memory rate limiting ศ™i nu Redis? - -**Rฤƒspuns**: -- **Simplitate**: Nu adaugฤƒ dependency nou -- **Suficient pentru scale mic-mediu**: - - In-memory e OK pentru <1000 users concurrent - - Planul curent: test cu 1 user, extend la 10-20 max -- **Upgrade path clar**: Dacฤƒ scalฤƒ, migrฤƒm la Redis -- **Code unchanged**: Interfaศ›a rฤƒmรขne aceeaศ™i - -### 5. De ce SQLite ศ™i nu PostgreSQL pentru bot DB? - -**Rฤƒspuns**: -- **Consistency**: Sistemul actual foloseศ™te SQLite -- **Zero infrastructure**: No server setup needed -- **Sufficient performance**: Telegram bot = low traffic -- **Easy backup**: Single file (`telegram_bot.db`) -- **Deployment simplicity**: Works รฎn Windows Service - ---- - -## ๐Ÿ”— Integrare cu Sistemul Existent - -### Flow Diagram - Ambele Metode - -``` - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ USER VREA Sฤ‚ SE AUTENTIFICE โ”‚ - โ”‚ รŽN TELEGRAM BOT โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ ALEGE METODA: โ”‚ - โ”‚ [Email + Parolฤƒ] sau [Web App] โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ โ”‚ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ โ”‚ - โ–ผ โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ METODA NOUฤ‚ โ”‚ โ”‚ METODA EXISTENTฤ‚ โ”‚ - โ”‚ Email + Parolฤƒ โ”‚ โ”‚ Web App Linking โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ โ”‚ - โ–ผ โ–ผ - 1. /login รฎn Telegram 1. Login รฎn web app (username+pass) - 2. Introdu email 2. Click "Link Telegram" - 3. Primeศ™ti cod pe email 3. Backend genereazฤƒ cod 8-char - 4. Introdu cod รฎn Telegram 4. Backend โ†’ POST /internal/save-code โ†’ Bot - 5. Introdu parolฤƒ 5. User: /start ABC123XY - 6. Bot verificฤƒ รฎn Oracle 6. Bot auto-link (fฤƒrฤƒ parolฤƒ din nou) - โ”‚ โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ USER AUTENTIFICAT รŽN BOT โ”‚ - โ”‚ JWT tokens saved รฎn telegram_usersโ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ COMENZI DISPONIBILE: โ”‚ - โ”‚ /companies, /dashboard, โ”‚ - โ”‚ /facturi, /trezorerie, etc. โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` - -### Database Schema - Complete View - -```sql --- EXISTING TABLE (no changes) -CREATE TABLE telegram_users ( - telegram_user_id INTEGER PRIMARY KEY, - username TEXT, - first_name TEXT, - last_name TEXT, - oracle_username TEXT, - jwt_token TEXT, - jwt_refresh_token TEXT, - token_expires_at TIMESTAMP, - linked_at TIMESTAMP, - last_active_at TIMESTAMP, - is_active BOOLEAN -); - --- EXISTING TABLE (no changes) -CREATE TABLE telegram_auth_codes ( - code TEXT PRIMARY KEY, -- 8-char code from web app - telegram_user_id INTEGER, - oracle_username TEXT, - created_at TIMESTAMP, - expires_at TIMESTAMP, - used BOOLEAN DEFAULT 0, - used_at TIMESTAMP -); - --- NEW TABLE (for email auth) -CREATE TABLE email_auth_codes ( - code TEXT PRIMARY KEY, -- 6-digit code sent via email - email TEXT NOT NULL, - oracle_username TEXT NOT NULL, - telegram_user_id INTEGER NOT NULL, - created_at TIMESTAMP, - expires_at TIMESTAMP, - used BOOLEAN DEFAULT 0, - used_at TIMESTAMP, - - INDEX idx_email (email), - INDEX idx_telegram_user_id (telegram_user_id) -); - --- EXISTING TABLE (no changes) -CREATE TABLE telegram_sessions ( - session_id TEXT PRIMARY KEY, - telegram_user_id INTEGER, - active_company_id INTEGER, - active_company_name TEXT, - conversation_state TEXT, - created_at TIMESTAMP, - updated_at TIMESTAMP, - expires_at TIMESTAMP -); -``` - -**Observaศ›ii:** -- `telegram_auth_codes` = pentru web app linking (EXISTING) -- `email_auth_codes` = pentru email auth (NEW) -- Ambele tabele coexistฤƒ, fiecare pentru flow-ul propriu -- `telegram_users` = comunฤƒ pentru ambele metode (linked users) - ---- - -## ๐Ÿšฆ Success Criteria - -### Implementarea e consideratฤƒ SUCCESS dacฤƒ: - -- [x] โœ… User poate sฤƒ facฤƒ `/login` รฎn Telegram -- [x] โœ… User poate introduce email ศ™i primeศ™te cod pe email -- [x] โœ… User poate introduce cod din email (valid 5 min) -- [x] โœ… User poate introduce parola Oracle -- [x] โœ… Bot verificฤƒ credenศ›ialele รฎn Oracle ศ™i genereazฤƒ JWT -- [x] โœ… User e autentificat ศ™i poate folosi comenzi (/companies, /dashboard, etc.) -- [x] โœ… Metoda veche (web app โ†’ /start cod) funcศ›ioneazฤƒ รฎn continuare -- [x] โœ… Ambele metode pot fi folosite de acelaศ™i user (switch รฎntre ele) -- [x] โœ… Codurile expirate sunt auto-ศ™terse -- [x] โœ… Mesajul cu parola e ศ™ters automat din chat -- [x] โœ… Rate limiting funcศ›ioneazฤƒ (max 3 emails/orฤƒ) -- [x] โœ… Error handling: mesaje clare pentru fiecare caz de eroare -- [x] โœ… Testare cu mmarius28@gmail.com funcศ›ioneazฤƒ end-to-end - ---- - -## ๐Ÿ“… Next Steps Dupฤƒ Implementare - -### Immediate (dupฤƒ deploy) - -1. **Testare cu user real (Marius)** - - Verificฤƒ flow complet cu mmarius28@gmail.com - - Test ambele metode de autentificare - - Valideazฤƒ email delivery ศ™i formatting - -2. **Monitoring** - - Watch logs pentru erori SMTP - - Monitor rate limiting triggers - - Check database growth (`email_auth_codes` table) - -### Short-term (1-2 sฤƒptฤƒmรขni) - -1. **Adaugฤƒ email pentru alศ›i useri** - - Identificฤƒ 5-10 useri pentru beta testing - - Adaugฤƒ email-uri รฎn Oracle `UTILIZATORI` table - - Anunศ›ฤƒ disponibilitatea noii metode - -2. **Collect feedback** - - UX pentru conversation flow - - Timing email delivery (sunt 5 min suficienศ›i?) - - Edge cases descoperite - -### Long-term (1-3 luni) - -1. **Analytics** - - Cรขศ›i useri folosesc fiecare metodฤƒ? - - Success rate pentru fiecare flow - - Common error patterns - -2. **Optimizฤƒri** - - Migrate rate limiting la Redis (dacฤƒ scalฤƒ) - - Adaugฤƒ email templates multiple (romรขnฤƒ + englezฤƒ) - - Consider migration de la SQLite la PostgreSQL (dacฤƒ >1000 users) - -3. **Feature extensions** - - Email verification pentru schimbare parolฤƒ - - Email notifications pentru events (reports ready, etc.) - - Multi-language support - ---- - -## ๐Ÿ“ž Contact & Support - -**Developer**: Claude Code (Anthropic) -**Project**: ROA2WEB - ERP Reports Application -**Date**: 2025-11-07 - -**Pentru รฎntrebฤƒri despre acest plan:** -- Review cod รฎn `reports-app/telegram-bot/` ศ™i `reports-app/backend/` -- Consultฤƒ `CLAUDE.md` pentru context general -- Check `TELEGRAM_COMMANDS.md` pentru comenzi existente - -**Resurse utile:** -- python-telegram-bot docs: https://docs.python-telegram-bot.org/ -- FastAPI docs: https://fastapi.tiangolo.com/ -- aiosmtplib docs: https://aiosmtplib.readthedocs.io/ - ---- - -## ๐ŸŽ‰ Conclusion - -Acest plan implementeazฤƒ autentificare **email + parolฤƒ (2FA)** pentru Telegram Bot รฎn mod **minimal invaziv**, pฤƒstrรขnd รฎntreaga funcศ›ionalitate existentฤƒ. - -**Key highlights:** -- โœ… **0 breaking changes** - metoda veche funcศ›ioneazฤƒ รฎn continuare -- โœ… **Simplu de implementat** - ~13h efort total -- โœ… **Securizat** - 2FA real cu rate limiting -- โœ… **Extensibil** - uศ™or de scalat pentru mai mulศ›i useri -- โœ… **User-friendly** - conversation flow natural - -**Ready to implement!** ๐Ÿš€ - ---- - -*Document generat: 2025-11-07* -*Versiune: 1.0* -*Status: Planning Phase - Ready for Implementation*